-2

I am trying to print the "result" of using table function, but when I tried to use the code here, I got something very strange:

    for (i in 1:4){
  print (table(paste("group",i,"$", "BMI_obese",sep=""), paste("group",i,"$","A1.1", sep="")))
}

This is the result in R output:

                 group1$A1.1
group1$BMI_obese           1

                 group2$A1.1
group2$BMI_obese           1

                 group3$A1.1
group3$BMI_obese           1

                 group4$A1.1
group4$BMI_obese           1

But when I type out the statement without typing inside the loop:

table(group2$BMI_obese, group2$A1.1)

I got what I want:

   1  2  3  4  5
0 51 20  9  8  0
1 37 20 15  6  4

Does anyone know which part of my for loop code is not correct or can be modified to fit my purpose of printing the loop table result?

Hi, all but now I have another problem. I am trying to add an inner loop which will take the column name as an argument, because I would like to loop through mulitiple column for each of the group data (i.e. for group1, I would like to have table of BMI_obese vs A1.1, BMI_obese vs A1.2 ... BMI_obese vs A1.15. This is my code, but somehow it is not working, I think it is because it is not recognizing the A1.1, A1.2,... as an column taking from the data group1, group2, group3, group4. But instead it is treated as a string I think. I am not sure how to fix it: for (i in 2:4) { for (j in c("A1.1","A1.2"))
{ print(with(get(paste0("group", i)),table(BMI_obese,j)))

            }               
        }   

I keep getting this error message: Error in table(BMI_obese, j) : all arguments must have the same length

john_w
  • 693
  • 1
  • 6
  • 25
  • 2
    You're making a table of strings (try table("a","b")). Can you elaborate on what larger problem you're trying to solve, and make a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)? – Heroka Jan 07 '16 at 07:31
  • 2
    Why not put all groups in a list and loop (`lapply`) over it to create the tables? That way you won't need to use `paste` or `get`. It's often recommended to keep similar objects in a list structure instead of cluttering R's global environment – talat Jan 07 '16 at 08:16
  • @john_w, you'd get better results if you focused your question down to something specific, with a reproducible example rather than keep tagging new "oh and.." onto an old question. Some minor investigation on your part should get you far. – doctorG Jan 11 '16 at 10:13

3 Answers3

1

Okay, you are trying to construct a variable name using paste and then do a table. You are simply passing the name of the variable to table, not the variable object itself. For this sort of approach you want to use get()

for (i in 1:4) {
    with(get(paste0("group", i), table(BMI_obese, A1.1))
}
#example saving as a list (using lapply rather than for loop)
group1 <- data.frame(x=LETTERS[1:10], y=(1:10)[sample(10, replace=TRUE)])
group2 <- data.frame(x=LETTERS[1:10], y=(1:10)[sample(10, replace=TRUE)])
result <- lapply(1:2, function(i) with(get(paste0("group", i)), table(x, y)))
#look at first six rows of each:
head(result[[1]])
head(result[[2]])

#example illustrating fetching objects from a string name
data(mtcars)
head(with(get("mtcars"), table(disp, cyl)))
head(with(get("mtcars"), table(disp, "cyl")))
#Error in table(disp, "cyl") : all arguments must have the same length
head(with(get("mtcars"), table(disp, get("cyl"))))
doctorG
  • 1,681
  • 1
  • 11
  • 27
  • Hi, I tried your code like this: for (i in 1:4) { + table(get("BMI_obese", paste0("group", i)), get("A1.1", paste0("group", i)))} but I got a error message of : Error in as.environment(pos) : no item called "group1" on the search list – john_w Jan 07 '16 at 08:30
  • Apologies. I've corrected the answer. The above now uses get() to get the actual data frame object from the string and then table() to tabulate your desired columns within that (data.frame) object. Now I'm at a proper computer I've tested on a simple data.frame and it should work for you. – doctorG Jan 07 '16 at 10:43
  • Hi doctorG, thanks for your answer. I think I am getting close to the final answer, but somehow when I tried your code in the R console, I get the error of: Error in table(BMI_obese, A1.1) : object 'BMI_obese' not found – john_w Jan 08 '16 at 03:31
  • It says BMI_obese object not found. BMI_obese is actually a column in the group1, group2, group3, group4 table. Also A1.1 is also one of the column in those tables. Somehow it says BMI_obese object is not found. – john_w Jan 08 '16 at 03:32
  • doctorG, I think your code works, but I have to modified a bit in order to print the result (it would be great if you happen to know how to store the result in a table , because I might want to store the result into a dataframe or table instead): for (i in 1:4) { print(with(get(paste0("group", i)), table(BMI_obese, A1.1)) )} The above print out all the result I want. Thank you – john_w Jan 08 '16 at 04:01
  • @john_w, If you're source'ing the file then, yes, you'd need to explicitly add a print. Exactly how you store the result depends on what you want to do with it. A list might serve you, and you can then access each table in the list. I'll edit my answer with an example. – doctorG Jan 08 '16 at 10:08
  • Hi, please see my edit to the question above. I have included a new part of the question about adding an inner loop but using the column name of the data as an argument but in this case the column I would like to use are named with A1.1, A1.2, A1.3 ..., A1.15, so I was hoping to loop through 1 to 15, but somehow it is not working. – john_w Jan 11 '16 at 08:21
  • @john_w, I've added some examples using get() that should show you the way to go. But do try to boil your problem down to a specific question rather than growing an existing question. Your gap distils down to understanding the basic distinction between an object and the string name of that object (and how get() gets you the object from the string name). – doctorG Jan 11 '16 at 10:19
  • Thanks. I think I understand more now about the differences. I have tried out your example which is really helpful for understanding. – john_w Jan 12 '16 at 03:13
0

Your types are used wrong. See the difference:

table(group2$BMI_obese, group2$A1.1)

and

table(paste(...),paste(...))

So what type does paste return? Certainly some string.

EDIT: paste(...) was not meant to be syntactically correct but an abbreviation for paste("group",i,"$", "BMI_obese",sep=""), or whatever you paste together.

paste(...) is returning some string. If you put that result into a table, you get a table of strings (the unexpected result that you got). What you want to do is acessing variables or fields with the name which is returned by your paste(...). Just an an eval to your paste like Daniel said and do it like this.

for (i in 1:4){
  print (table(eval(paste("group",i,"$", "BMI_obese",sep="")),eval(paste("group",i,"$","A1.1", sep=""))))
}
Hühnergott
  • 76
  • 2
  • 4
  • Hi Huhnergott, could you explain little bit more what you are trying to show here. Sorry I am not familiar with the syntax of R, could you explain what you are trying to show with : table(paste(...), paste(...)) – john_w Jan 07 '16 at 08:24
  • Because I got this message in R when I typed table(paste(...),paste(...)) :Error in table(paste(...), paste(...)) : '...' used in an incorrect context – john_w Jan 07 '16 at 08:25
  • Hi Huhnergott, your code produces exactly the same thing I have when I using my wrong code above. Adding "eval" doesn't seem to help in this case. – john_w Jan 11 '16 at 06:37
  • Hi, please see my edit to the question above. I have included a new part of the question about adding an inner loop but using the column name of the data as an argument but in this case the column I would like to use are named with A1.1, A1.2, A1.3 ..., A1.15, so I was hoping to loop through 1 to 15, but somehow it is not working. – john_w Jan 11 '16 at 08:20
0

You could also use a combination of eval and parse like this:

x1 <- c(sample(10, 100, replace = TRUE))
y1 <- c(sample(10, 100, replace = TRUE))
table(eval(parse(text = paste0("x", 1))),
      eval(parse(text = paste0("y", 1))))

But I'd also say it is not the nicest practice to access variables that way...

Daniel Fischer
  • 3,280
  • 1
  • 18
  • 29
  • Hi, please see my edit to the question above. I have included a new part of the question about adding an inner loop but using the column name of the data as an argument but in this case the column I would like to use are named with A1.1, A1.2, A1.3 ..., A1.15, so I was hoping to loop through 1 to 15, but somehow it is not working. – john_w Jan 11 '16 at 08:20