For循环根据名称模式组合不同的变量

时间:2018-09-19 09:07:25

标签: r for-loop

我需要组合以特定字符结尾的变量集。变量以以下方式命名(data = df):

id   A_1   A_2   A_3   B_1   B_2   B_3   C_1   C_2   C_3
1    7     2     1     6     7     4     3     9     0
2    8     5     2     9     7     2     1     6     1
3    5     4     0     8     6     4     1     7     0

现在说“组合”意味着我需要以_1,_2等等结尾的每组变量的rowMeans。

所以我可以这样做:

rowMeans(df[,c("A_1","B_1","C_1")])
rowMeans(df[,c("A_2","B_2","C_2")])
rowMeans(df[,c("A_3","B_3","C_3")])

问题是我有很多这样的变量结尾,并且每个结尾我基本上都会得到一行代码。因此,我想知道是否存在使用for循环执行相同操作的更智能方法。

此for循环将需要包含结尾的i(1:n)和一个稳定的名称模式,即“ A _”,“ B_”和“ C_”,然后运行rowMeans()。但是由于我不是编写循环的专家,所以我不知道如何在实践中做到这一点。

3 个答案:

答案 0 :(得分:4)

我们可以使用paste0生成列名称,选择其中的rowMeans,然后使用lapply将其添加到新列中。

n <- 3
df[paste0(1:n, "_mean")] <- lapply(paste0("_", 1:n, "$"), function(x) {
 rowMeans(df[grepl(x, names(df))])
})

df

#  id A_1 A_2 A_3 B_1 B_2 B_3 C_1 C_2 C_3   1_mean   2_mean   3_mean
#1  1   7   2   1   6   7   4   3   9   0 5.333333 6.000000 1.666667
#2  2   8   5   2   9   7   2   1   6   1 6.000000 6.000000 1.666667
#3  3   5   4   0   8   6   4   1   7   0 4.666667 5.666667 1.333333

答案 1 :(得分:3)

您可以使用tidyverse来做到这一点:

df %>% gather(k,v,-id) %>% 
  mutate(g=substring(k,3)) %>%
  group_by(id,g) %>% summarise(n=mean(v)) %>%
  spread(g,n)
## A tibble: 3 x 4
## Groups:   id [3]
#     id   `1`   `2`   `3`
#  <int> <dbl> <dbl> <dbl>
#1     1  5.33  6     1.67
#2     2  6     6     1.67
#3     3  4.67  5.67  1.33

答案 2 :(得分:1)

您可以将paste0lapply一起使用,如下所示:

n_numbers <- 1:3
n_letters <- 1:3 # change here to extend

col_list <- lapply(n_numbers, function(x) paste0(LETTERS[n_letters], "_", x)) #generates the names

dat_list <- lapply(col_list, function(x) dat[x]) # applies subsetting to dat

lapply(dat_list, rowMeans) # rowMeans

# [[1]]
# [1] 5.333333 6.000000 4.666667
# 
# [[2]]
# [1] 6.000000 6.000000 5.666667
# 
# [[3]]
# [1] 1.666667 1.666667 1.333333

使用的数据:

tt <- "id   A_1   A_2   A_3   B_1   B_2   B_3   C_1   C_2   C_3
1    7     2     1     6     7     4     3     9     0
2    8     5     2     9     7     2     1     6     1
3    5     4     0     8     6     4     1     7     0"

dat <- read.table(text = tt, header = T)