如何设置循环以分配大量变量

时间:2019-07-19 21:28:46

标签: r loops

我刚开始在心理课上使用R,所以请放轻松。我在For循环上观看了一堆youtube视频,但没有一个回答我的问题。我有4个数据帧(A,B,C,D),每个都有25列。我想将每个数据帧的第n列组合在一起,然后将它们另存为对象,如下所示:

Q1 <- cbind(A[1], B[1], C[1], D[1])
Q2 <- cbind(A[2], B[2], C[2], D[2])

如何设置一个循环来对全部25个循环执行此操作,所以我不必手动进行循环?

预先感谢

我的每个数据框都看起来像这样(列标题反映了数据框的字母(即B具有QB1,QB2等。

   QA1 QA2 QA3 QA4 QA5 QA6 QA7 QA8 QA9 QA10 QA11 QA12 QA13 QA14 QA15
1    1   2   2   0   0   2   0   1   0    0    0    0    0    0    0
2    0   0   0   0   0   0   0   0   0    1    0    0    0    1    0
3    1   0   0   0   0   0   1   0   0    2    1    1    0    0    0
4    1   0   0   0   0   0   1   1   0    1    0    2    0    0    0

2 个答案:

答案 0 :(得分:3)

为了在for循环中执行此操作,您需要使用assign()中的baseReval_tidy()中的sym()rlang()。基本上,您需要将字符串作为变量求值。

创建模拟数据


library(rlang)
nrows = 10
ncols = 25
df_names <- c("A","B","C","D")
for(df_name in df_names){
    # assign value to a string as variable
    assign(
        df_name,
        as.data.frame(
            matrix(
                data = sample(
                    c(0,1),
                    size = nrows * ncols,
                    replace = TRUE
                ),
                ncol = 25
            )
        )
    )

    # rename columns
    assign(
        df_name,
        setNames(eval_tidy(sym(df_name)),paste0("Q",df_name,1:ncols))
    )
}

显示A


> head(A)

  QA1 QA2 QA3 QA4 QA5 QA6 QA7 QA8 QA9 QA10 QA11 QA12 QA13 QA14 QA15 QA16 QA17 QA18 QA19 QA20 QA21 QA22 QA23 QA24 QA25
1   1   1   0   0   1   0   1   0   1    1    0    0    1    1    1    0    0    1    0    0    1    1    0    1    1
2   0   1   0   1   1   1   1   0   1    1    1    1    0    0    0    1    0    1    1    0    1    0    1    1    0
3   0   0   0   1   1   0   1   0   1    0    0    1    0    0    0    1    1    1    1    0    0    0    1    1    1
4   0   0   1   1   1   0   0   1   1    1    1    0    1    1    0    1    0    0    0    1    0    1    1    1    1
5   1   1   0   1   1   1   1   1   1    0    1    0    0    0    0    0    1    0    1    0    1    1    0    1    1
6   1   1   0   0   1   1   0   1   1    1    0    1    0    1    1    0    1    0    0    1    1    0    1    1    0

回答您的问题:

这将创建从Q1Q25的25个变量:


# assign dataframes from Q1 to Q25
for(i in 1:25){
    new_df_name <- paste0("Q",i)
    # initialize Qi with the same number of rows as A,B,C,D ...
    assign(
        new_df_name,
        data.frame(tmp = matrix(NA,nrow = rows))
    )
    # loop A,B,C,D ... and bind them
    for(df_name in df_names){
        assign(
            new_df_name,
            cbind(
                eval_tidy(sym(new_df_name)),
                eval_tidy(sym(df_name))[,i,drop = FALSE]
            )
        )
    }
    # drop tmp to clean up
    assign(
        new_df_name,
        eval_tidy(sym(new_df_name))[,-1]
    )
}

显示结果:

> Q25
   QA25 QB25 QC25 QD25
1     1    0    1    1
2     0    1    0    0
3     1    1    0    0
4     1    0    1    1
5     1    1    0    0
6     0    1    1    1
7     1    0    0    0
8     0    0    0    1
9     1    1    1    0
10    0    0    1    1

如果使用map()将结果保存在列表中,则代码应该容易得多。主要的复杂性是将值分配给单独的变量。

答案 1 :(得分:0)

您可以在dplyr循环中组合一些for动词,以合并每个数据集中的列并将其分配给25个新对象。

# merge data, gather, split by var numbers, assign each df to environment
for (i in 1:25) {
  df <- cbind(q1,q2,q3,q4) %>% mutate(id=row_number()) %>% 
    gather(k,v,-id) %>% 
    mutate(num=sub('A|B|C|D','',k)) %>% 
    filter(num==i) %>% select(-num) %>% spread(k,v)
  assign(paste0('df',i),df)
}

ls(pattern = 'df')

 [1] "df1"  "df10" "df11" "df12" "df13" "df14" "df15" "df16" "df17" "df18" "df19" "df2" 
[13] "df20" "df21" "df22" "df23" "df24" "df25" "df3"  "df4"  "df5"  "df6"  "df7"  "df8" 
[25] "df9" 

创建初始4个玩具数据帧的代码。

# create four toy data frames
q1 <- data.frame(matrix(runif(100),ncol=25))
q2 <- data.frame(matrix(runif(100),ncol=25))
q3 <- data.frame(matrix(runif(100),ncol=25))
q4 <- data.frame(matrix(runif(100),ncol=25))

# set var names for each toy data
names(q1) <- sub('X','A',names(q1))
names(q2) <- sub('X','B',names(q2))
names(q3) <- sub('X','C',names(q3))
names(q4) <- sub('X','D',names(q4))