【问题标题】:R Mutate Column That Represents the Mean of Many Other ColumnsR 变异列代表许多其他列的平均值
【发布时间】:2018-05-22 21:25:23
【问题描述】:

我正在尝试在我的 DataFrame 中添加一个列,该列代表许多其他列(代表单个构造的项目)的平均值。

数据框有许多其他列,但特别是 eng1、eng2、eng3...engN 列,其中 N 是一个很大的数字,我想取所有 eng* 列的平均值并将该平均值作为新列添加到我的数据集。

我可以使用以下代码做到这一点:

narrow_ds # ... initialization of dataframe
library(dplyr)
narrow_ds <- bind_cols(narrow_ds, (narrow_ds %>% 
select(starts_with("eng")) %>% mutate(eng=rowMeans(., na.rm=TRUE))) %>% 
select(eng))

似乎拥有 na.rm=TRUE 要求迫使我跳过一些障碍。

我的问题是是否有更直接的方法可以做到这一点?

【问题讨论】:

  • 你想取所有列的平均值,还是只取一个子集?
  • 它应该是(相当多)以 eng 开头的列的平均值。数据集中还有其他列我不想包含在平均值中。 (我将编辑问题以澄清。)

标签: r dplyr tidyverse


【解决方案1】:

您的方向非常正确。您可以通过调整代码来避免bind_cols。此外,即使在rowMeans 中也支持NA。我已经修改了@Tung 使用的样本数据,以包含少量NAs。解决方案可以是:

选项#1:以与 OP 类似的方法使用 dplyr

library(dplyr)
DF %>% mutate(eng = rowMeans(select(.,starts_with("eng")), na.rm = TRUE))

# # A tibble: 4 x 5
#      id  eng1  eng2  eng3   eng
#   <int> <dbl> <dbl> <dbl> <dbl>
# 1     1  50.0    NA  20.0  35.0
# 2     2  NA     100  10.0  55.0
# 3     3  20.0   150  80.0  83.3
# 4     4  30.0   200  40.0  90.0

选项#2:使用apply

DF$eng <- apply(DF[,grep("eng",names(DF))], 1, mean, na.rm = TRUE)

DF
# # A tibble: 4 x 5
#      id  eng1  eng2  eng3   eng
#    <int> <dbl> <dbl> <dbl> <dbl>
# 1     1  50.0    NA  20.0  35.0
# 2     2  NA     100  10.0  55.0
# 3     3  20.0   150  80.0  83.3
# 4     4  30.0   200  40.0  90.0

样本数据:

DF = data_frame(id = 1:4,
                eng1 = c(50, NA, 20, 30), 
                eng2 = c(NA, 100, 150, 200), 
                eng3 = c(20, 10, 80, 40))

【讨论】:

  • 感谢您提供的两个选项。
【解决方案2】:

从@MKR 中窃取样本数据,以 R 为基础:

DF$eng <- rowMeans(DF[startsWith(names(DF),"eng")], na.rm = TRUE)

# # A tibble: 4 x 5
#      id  eng1  eng2  eng3      eng
#   <int> <dbl> <dbl> <dbl>    <dbl>
# 1     1    50    NA    20 35.00000
# 2     2    NA   100    10 55.00000
# 3     3    20   150    80 83.33333
# 4     4    30   200    40 90.00000

【讨论】:

  • startsWith(),之前没有遇到过这个功能。上帝召唤。
  • 感谢您的快速回复。这是我在代码中使用的那个。
【解决方案3】:

在同一个问题苦苦挣扎之后,我认为使用“dplyr”中的“rowwise()”命令和用“c ()" 在想要的操作中:

C1<-c(3,2,4,4,5)
C2<-c(3,7,3,4,5)
C3<-c(5,4,3,6,3)
DF<-data.frame(ID=c("A","B","C","D","E"),C1=C1,C2=C2,C3=C3)


library(dplyr)

DF <- DF %>% 
     rowwise() %>% mutate(Avg = (mean(c(C1, C2, C3), na.rm = T))) 

DF
   ID    C1    C2    C3    Avg
  <fct> <dbl> <dbl> <dbl> <dbl>
1 A         3     3     5  3.67
2 B         2     7     4  4.33
3 C         4     3     3  3.33
4 D         4     4     6  4.67
5 E         5     5     3  4.33

还可以确保此操作在单个数据帧上结束,执行以下操作:

DF <- as.data.frame(DF %>% 
         rowwise() %>% mutate(Avg = (mean(c(C1, C2, C3), na.rm = T)))) 

【讨论】:

  • 虽然此代码可能会解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的答案以添加解释并说明适用的限制和假设。 From Review
【解决方案4】:

您可以使用pmap_dbl 循环遍历数据框的每一行。这是一个带有一些随机数据的示例

library(tidyverse)

DF = data_frame(eng1 = c(50, 40, 20, 30), 
                eng2 = c(130, 100, 150, 200), 
                eng3 = c(20, 10, 80, 40))
DF

#> # A tibble: 4 x 3
#>    eng1  eng2  eng3
#>   <dbl> <dbl> <dbl>
#> 1    50   130    20
#> 2    40   100    10
#> 3    20   150    80
#> 4    30   200    40

DF %>% 
  select(starts_with("eng")) %>% 
  mutate(eng = pmap_dbl(., sum))

#> # A tibble: 4 x 4
#>    eng1  eng2  eng3   eng
#>   <dbl> <dbl> <dbl> <dbl>
#> 1    50   130    20   200
#> 2    40   100    10   150
#> 3    20   150    80   250
#> 4    30   200    40   270

# or define a function
sumAll <- function(...) {
  x = c(...)
  sum(x, na.rm = TRUE)
}

DF %>% 
  select(starts_with("eng")) %>% 
  mutate(eng = pmap_dbl(., sumAll))

#> # A tibble: 4 x 4
#>    eng1  eng2  eng3   eng
#>   <dbl> <dbl> <dbl> <dbl>
#> 1    50   130    20   200
#> 2    40   100    10   150
#> 3    20   150    80   250
#> 4    30   200    40   270

reprex package (v0.2.0) 于 2018 年 5 月 22 日创建。

【讨论】:

  • 感谢 pmap_dbl 的提醒。
【解决方案5】:
# Example data
set.seed(1)
dtf <- as.data.frame(matrix(sample(1:10000), ncol=1000))
nam <- replicate(ncol(dtf), paste(sample(LETTERS, 10, replace=TRUE), collapse=""))
colnames(dtf) <- nam

我没有将列命名为“eng*”,但这在功能上是相同的。
只有名称以A 开头的列才会被平均。

eng <- rowMeans(dtf[, grep("^A", colnames(dtf))], na.rm=TRUE)
dtf <- cbind(eng, dtf)

summary(dtf)[,1:4]
# #      eng         BRTCBDWVWA     COCSSUQNLA     FIOULRNUXL  
# Min.   :4535   Min.   : 618   Min.   :1764   Min.   : 134  
# 1st Qu.:4780   1st Qu.:2922   1st Qu.:3805   1st Qu.:2254  
# Median :5187   Median :6008   Median :5916   Median :3604  
# Mean   :5107   Mean   :5513   Mean   :5580   Mean   :4174  
# 3rd Qu.:5337   3rd Qu.:8386   3rd Qu.:7557   3rd Qu.:5840  
# Max.   :5739   Max.   :9442   Max.   :9903   Max.   :9329  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 2017-10-04
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多