1

Using the file below, I am trying to creating 2 scatterplots. One scatterplot compares the 2nd and 3rd column when the first column is equal to "coat" and the second scatterplot compares the 2nd and third column when the first column is equal to "hat"

file.txt

clothing,freq,temp
coat,0.3,10
coat,0.9,0
coat,0.1,20
hat,0.5,20
hat,0.3,15
hat,0.1,5

This is the script I have written

script.R

rates = read.csv("file.txt")
for(i in unique(rates[1])){
        plot(unlist(rates[2])[rates[1] == toString(i)],unlist(rates[3])[rates[1] == toString(i)])
}

I receive this error when running it

Error in plot.window(...) : need finite 'xlim' values
Calls: plot -> plot.default -> localWindow -> plot.window
In addition: Warning messages:
1: In min(x) : no non-missing arguments to min; returning Inf
2: In max(x) : no non-missing arguments to max; returning -Inf
3: In min(x) : no non-missing arguments to min; returning Inf
4: In max(x) : no non-missing arguments to max; returning -Inf
Execution halted

The script works if I replace if I replace "toString(i)" with "hat" but can obviously only make one of the scatterplots.

.

EDIT

I edited my script slightly. It creates a graph for the first iteration through the loop but not for any iteration after the first. This is my script

rates = read.csv("file.txt")
for(i in unique(rates[,1])){
        plot(unlist(rates[2])[rates[1] == toString(i)],unlist(rates[3])[rates[1] == toString(i)])
        file.rename("Rplots.pdf", paste(i,".pdf",sep=""))
}

This is what happens when I execute the script

name@server:/directory> ./script.R 
Warning message:
In file.rename("Rplots.pdf", paste(i, ".pdf", sep = "")) :
  cannot rename file 'Rplots.pdf' to 'hat.pdf', reason 'No such file or directory'
name@server:/directory> ls
coat.pdf  file.txt  script.R*
Sam
  • 1,765
  • 11
  • 82
  • 176

5 Answers5

1

try this:

rates = read.table("file.txt",sep=',',header=TRUE)

cloth_type<-unique(rates[,1])   

for (i in 1:length(cloth_type)){

    dev.new()

    index_included=which(rates[,1]==cloth_type[i])

    plot(rates[index_included,2],rates[index_included,3],main=cloth_type[i],
    xlab="freq ", ylab="temp ", pch=19)

}   
Munish
  • 667
  • 3
  • 13
  • 34
  • I would prefer to use a solution closer to what I posted in my question because I'm unfamiliar with R and I don't understand a lot of your solution (such as dev.new(), which, and what exactly is going on before the first two commas of your plot function). Is there a way to do it like my code? In my edit I use `unique(rates[,1])` instead of `unique(rates[1])` and I feel like it is almost working but I can only create one graph. – Sam Jul 20 '17 at 02:32
  • 1
    dev.new() opens a new plot window each time, I placed it in the loop to plot both scatter plots, one at a time. Another way is divide the screen into 2 parts using par(...) and plot the two on each part – Munish Jul 20 '17 at 17:39
  • I'm running my working script on my actual program but when I get to about 50 graphs that I have created I get this error dev.new(): using pdf(file="Rplots1.pdf") Error in (function (file = ifelse(onefile, "Rplots.pdf", "Rplot%03d.pdf"), : too many open devices Calls: dev.new -> do.call -> Execution halted " – Sam Jul 20 '17 at 19:36
1

Maybe the dplyr package would be helpful.

To install the package:

install.packages('dplyr')

Then you can use the filter function to generate separate your separate dataframes:

library('dplyr')

rates <- read.csv("file.txt")

cloathTypes <- unique(rates$clothing)

for(cloath in cloathTypes){
  d <- filter(rates, clothing == cloath)
  plot(d$freq, d$temp, xlab = 'Freq', ylab='Temp', main=cloath)
}
0

I think your issue is arising from calling unique() on a data.frame, which produces another data.frame rather than a vector to iterate over. Provided your global options import strings as factors, you should be able to output the plots side-by-side as follows:

## input data
rates = data.frame(clothing = c(rep("coat", 3), rep("hat", 3)), 
                   freq = c(0.3, 0.9, 0.1, 0.5, 0.3, 0.1), 
                   temp = c(10, 0, 20, 20, 15, 5))
## store original plotting parameters
op = par(no.readonly = TRUE)
## modify plotting parameters to produce side-by-side plots
par(mfrow = c(1, 2))
## output plots
for(i in levels(rates[,1])){
  plot(rates[,2][rates[,1] == i], rates[,3][rates[,1] == i])
}
## reset plotting pars
par(op)

If you want to produce separate plots just remove the par lines.

Shaun Wilkinson
  • 473
  • 1
  • 4
  • 11
0

You can do this pretty easily with ggplot

Your data as a data.frame

df <- data.frame(clothing=c(rep("coat",3),rep("hat",3)),
             freq=c(0.3,0.9,0.1,0.5,0.3,0.1),
             temp=c(10,0,20,20,15,5),
             stringsAsFactors=F)

Plotting freq on x, temp on y, and coloring points by clothing

ggplot(df, aes(freq, temp, colour=clothing)) +
geom_point()
CPak
  • 13,260
  • 3
  • 30
  • 48
0

Change for(i in unique(rates[1])) to for(i in unique(rates[,1])) and add dev.new() into the for loop

rates = read.csv("file.txt")
for(i in unique(rates[,1])){
        dev.new()
        plot(unlist(rates[2])[rates[1] == toString(i)],unlist(rates[3])[rates[1] == toString(i)])
        file.rename("Rplots.pdf", paste(i,".pdf",sep=""))
}
Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
Sam
  • 1,765
  • 11
  • 82
  • 176