如何按列名计算rowMeans,而不是列号

时间:2018-05-01 11:28:25

标签: r statistics

我有以下df bhs1

structure(list(bhs1_1 = c(NA, 1, NA, 2, 1, 2, 2, 2, 1, 2, 1, 
2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2), bhs1_2 = c(NA, 
2, NA, 2, 1, 1, 2, 1, 2, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 
1, 1, 2, 2, 2), bhs1_3 = c(NA, 1, NA, 2, 2, 2, 2, 2, 2, 2, 1, 
2, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2), bhs1_4 = c(NA, 
2, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 
1, 1, 2, 1, 1), bhs1_5 = c(NA, 1, NA, 1, 2, 2, 2, 2, 2, 2, 1, 
2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1), bhs1_6 = c(NA, 
1, NA, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, NA, 2, 1, 
2, NA, 1, 1, 2), bhs1_7 = c(NA, 1, NA, 1, 2, 1, 1, 1, 1, 1, 2, 
1, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1), bhs1_8 = c(NA, 
2, NA, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 
2, 1, 2, 2, 2), bhs1_9 = c(NA, 1, NA, 2, 1, 1, 1, 1, 2, 1, 2, 
1, 1, 1, NA, 1, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2), bhs1_10 = c(NA, 
2, NA, 1, 2, 2, 2, 2, 1, 2, 1, 1, NA, 2, 1, 1, 1, 2, 1, 2, 2, 
2, 2, 1, 1, 2), bhs1_11 = c(NA, 2, NA, 2, 2, 1, 1, 1, 2, 1, 1, 
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, 2, 2, 1), bhs1_12 = c(NA, 
2, NA, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 
1, 2, 2, 1, 1), bhs1_13 = c(NA, 1, NA, 1, 2, 2, 2, 2, 1, 1, 1, 
2, 2, 2, 2, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2), bhs1_14 = c(NA, 
2, NA, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 
1, 1, 2, 2, 1), bhs1_15 = c(NA, 1, NA, 2, 2, 2, 2, 2, 2, 1, 2, 
2, 2, 2, 1, 1, 2, 2, 2, NA, 2, 2, 2, 1, 2, 2), bhs1_16 = c(NA, 
2, NA, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 1, 
1, 2, 2, 2, 2), bhs1_17 = c(NA, 2, NA, 2, 2, 1, 1, 1, 2, 1, 1, 
1, 1, 1, 2, 2, 1, NA, 2, 2, 1, 1, 1, 2, 2, 2), bhs1_18 = c(NA, 
1, NA, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 
1, 1, 2, 1, 1), bhs1_19 = c(NA, 1, NA, 2, 1, 2, 2, 2, 1, 2, 2, 
2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, 2), bhs1_20 = c(NA, 
2, NA, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 
1, 1, 2, 2, 2)), row.names = c(NA, -26L), class = c("tbl_df", 
"tbl", "data.frame")) 

bhs1已通过as_tibble()

我对计算新变量bhs1$total感兴趣,这是变量bhs1_1:bhs1_20的按比例分配的平均值。按比例分配的原因是,可以将缺失值的观测值与没有缺失值的观测值进行比较。冒着说明显而易见的风险:

  • 观察1可能只有18个变量的数据,所以我需要对记录的变量求和,忽略NAs,然后除以18得到一个可比较的平均值,
  • 观察2谁拥有20个变量的数据,谁将总计记录变量除以20.

我知道(虽然还不知道如何执行)多重插补,但我不想将此用于此练习。

我尝试过以下代码:

# A tibble: 908 x 21
   bhs1_1 bhs1_2 bhs1_3 bhs1_4 bhs1_5 bhs1_6 bhs1_7 bhs1_8 bhs1_9
 *  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
 1     NA     NA     NA     NA     NA     NA     NA     NA     NA
 2      1      2      1      2      1      1      1      2      1
 3     NA     NA     NA     NA     NA     NA     NA     NA     NA
 4      2      2      2      1      1      2      1      2      2
 5      1      1      2      1      2      1      2      2      1
 6      2      1      2      1      2      2      1      2      1
 7      2      2      2      1      2      2      1      2      1
 8      2      1      2      1      2      2      1      2      1
 9      1      2      2      1      2      2      1      1      2
10      2      2      2      1      2      1      1      2      1
# ... with 898 more rows, and 12 more variables: bhs1_10 <dbl>,
#   bhs1_11 <dbl>, bhs1_12 <dbl>, bhs1_13 <dbl>, bhs1_14 <dbl>,
#   bhs1_15 <dbl>, bhs1_16 <dbl>, bhs1_17 <dbl>, bhs1_18 <dbl>,
#   bhs1_19 <dbl>, bhs1_20 <dbl>, meanTest <dbl>

哪个按预期工作。但是,当我输入列名而不是列号时,它会失败:

> bhs1$meanTest <- rowMeans(bhs1[,"bhs1_1":"bhs1_20"], na.rm=TRUE)

Error in "bhs1_1":"bhs1_20" : NA/NaN argument
   5. check_names_df(j, x)
   4. `[.tbl_df`(bhs1, , "bhs1_1":"bhs1_20")
   3. bhs1[, "bhs1_1":"bhs1_20"]
   2. is.data.frame(x)
   1. rowMeans(bhs1[, "bhs1_1":"bhs1_20"], na.rm = TRUE)

我认为使用变量/列名而不是列号要简单得多。是否有一种优雅的方式来编写代码来满足这个用例?如果是这样,有人可以指出我正确的方向和/或提供样品吗?

提前感谢您的考虑和帮助。

1 个答案:

答案 0 :(得分:1)

我们需要一个名字载体

nm1 <- paste0("bhs1_", 1:20)
bhs1$meanTest <- rowMeans(bhs1[nm1], na.rm = TRUE)

如果名称没有模式,我们有兴趣在起始名和停止名之间进行分组,那么使用match获取列索引,获取序列(:

nm1 <- Reduce(`:`, match(c("bhs1_1", "bhs1_20"), names(bhs1)))

并在rowMeans

中使用它

如果我们使用tidyverse,我们可以指定范围(:

bhs1 <- bhs1 %>%
          select(bhs1_1:bhs1_20) %>% #can replace with 'nm1'
          rowMeans(., na.rm = TRUE) %>%
          bind_cols(bhs1, meanTest = .)

如果我们需要在多组列上执行rowMeans,请使用map2中的purrr,将其作为“开始”和“结束”的状态列表传递'{1}}中的列名称,然后通过评估(map2)后面的select来获取!!

rowMeans

或者我们可以作为字符串向量传递,然后转换为符号(library(purrr) map2_df(quos(bhs1_1, bhs1_4), quos(bhs1_5, bhs1_8), ~ bhs1 %>% select((!! .x) : (!! .y)) %>% rowMeans(., na.rm = TRUE)) %>% bind_cols(bhs1, .) 中的sym)并评估(rlang

!!