0

How to combine for loop with function I made in R? , and want to loop in satis.list. However, it failed to loop..

I made a function 'site_table' below.

> satis.list <- paste0("s1_", 1:19)
> satis.list <- c(satis.list,"s2","s3","s4")
> satis.list
 [1] "s1_1"  "s1_2"  "s1_3"  "s1_4"  "s1_5"  "s1_6"  "s1_7"  "s1_8"  "s1_9" 
[10] "s1_10" "s1_11" "s1_12" "s1_13" "s1_14" "s1_15" "s1_16" "s1_17" "s1_18"
[19] "s1_19" "s2"    "s3"    "s4"   

And make a function site_table below.

> site_table = function(var){
+   var_name <- eval(substitute(var),eval(work.data))
+   a <- table(var_name,work.data$site)
+   b.list <- list(a[2,1], a[2,2], a[2,3])
+   b.data <- data.frame(t(b.list))
+   b.data
+ }

I want to repeat this like below from "s1_1" to "s4" in satis.list

> site_table(s1_1)
  X1 X2 X3
1  2  2  7
> site_table(s1_2)
  X1 X2 X3
1  2  3  4
> site_table(s1_3)
  X1 X2 X3
1  3  1  4

I tried to using this code but failed.

> c.data <- data.frame()
> for(i in satis.list){
+   site_table(i)
+   c.data <- rbind(c.data, b.data)
+ }
 Error in table(var_name, work.data$site) : 
  all arguments must have the same length 

It is the output what I want to make lastly.

  Row.names X1 X2 X3
1    s1_1    2  2  7
1    s1_2    2  3  4
1    s1_3    3  1  4
  • Some data seems to be missing to reproduce your example. What is the variable `work.data`? Anyway, you need to write `b.data <- site_table(i)` in your loop. The function does not by itself return a variable `b.data` (that is a local variable within the function). – M. Papenberg Mar 13 '20 at 08:06
  • Hi. Besides the missing data (see https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/5963610#5963610 for how to make a good reproducible example) there are several issues with you code. The error you get is related to the fact that inside `site_table()` in the line ` a <- table(var_name,work.data$site)` you try to table a vector of length 1 and a vector of length > 1. Try yourself with `table("var", mtcars$mpg)`. – stefan Mar 13 '20 at 08:21
  • Run your function like that: `site_table(s2)` and tell me what was the result – Adamm Mar 13 '20 at 12:03
  • @M.Papenberg Sorry to missing data. `example.data <- data.frame( site = c(1,1,1,2,2,2,3,3,3), s1_1 = c(NA,NA,NA,1,NA,NA,1,1,NA), s1_2 = c(1,NA,NA,1,1,NA,1,1,1), s1_3 = c(1,1,1,1,1,NA,1,NA,NA) )` – Junghun Yoo Mar 16 '20 at 08:47
  • @stefan Umm, I want to make a repeat like below. `table(work.data$s1_1,work.data$site) table(work.data$s1_2,work.data$site) ... repeat in satis.list from "s1_1" to "s4" ` This coding runs, and function "site_table" also runs seperately like site_table(s1_1), site_table(s1_2). However, when I put in a loop, a error came out. – Junghun Yoo Mar 16 '20 at 08:55
  • @Adamm, The result of `site_table(s2)` is not much different from that of `site_table(s1_2)`. All data except site are composed of 1 and missing (NA), and I want to see the number of 1 per site. The number of site is 3. – Junghun Yoo Mar 16 '20 at 08:59

1 Answers1

0

If I got you right. You want a table which shows you the number of "1" at each site and for each "element" of satis list. The following approach first converts the data to long fomrat, filters out missings and then tables site vs. the other columns in your original dataset. Try this:

library(dplyr)
library(tidyr)

example.data <- data.frame( site = c(1,1,1,2,2,2,3,3,3), s1_1 = c(NA,NA,NA,1,NA,NA,1,1,NA), s1_2 = c(1,NA,NA,1,1,NA,1,1,1), s1_3 = c(1,1,1,1,1,NA,1,NA,NA) )

example.data
#>   site s1_1 s1_2 s1_3
#> 1    1   NA    1    1
#> 2    1   NA   NA    1
#> 3    1   NA   NA    1
#> 4    2    1    1    1
#> 5    2   NA    1    1
#> 6    2   NA   NA   NA
#> 7    3    1    1    1
#> 8    3    1    1   NA
#> 9    3   NA    1   NA

# Using gather 
example.data %>% 
  gather(satis.list, value, -site) %>% 
  filter(!is.na(value)) %>% 
  select(satis.list, site) %>% 
  table()
#>           site
#> satis.list 1 2 3
#>       s1_1 0 1 2
#>       s1_2 1 2 3
#>       s1_3 3 2 1

Created on 2020-03-16 by the reprex package (v0.3.0)

stefan
  • 90,330
  • 6
  • 25
  • 51