【问题标题】:Calculate metrics for multiple columns based on subsets defined by other columns根据其他列定义的子集计算多列的指标
【发布时间】:2018-12-26 13:48:00
【问题描述】:

我想为数据框中某些列的子集计算简单的汇总指标,其中子集基于同一数据框的其他列中的信息。让我举例说明:

colA <- c(NA,2,3,NA,NA,3,9,5,6,1)
colB <- c(9,3,NA,2,2,4,6,1,9,9)
colC <- c(NA,NA,5,7,3,9,8,1,2,3)
colAA <- c(NA,NA,6,NA,NA,NA,1,7,9,4)
colBB <- c(NA,2,NA,7,8,NA,2,7,9,4)
colCC <- c(NA,NA,3,7,5,8,9,9,NA,3)

df <- data.frame(colA,colB,colC,colAA,colBB,colCC)

> df
   colA colB colC colAA colBB colCC
1    NA    9   NA    NA    NA    NA
2     2    3   NA    NA     2    NA
3     3   NA    5     6    NA     3
4    NA    2    7    NA     7     7
5    NA    2    3    NA     8     5
6     3    4    9    NA    NA     8
7     9    6    8     1     2     9
8     5    1    1     7     7     9
9     6    9    2     9     9    NA
10    1    9    3     4     4     3

这里 colAA 应该由 colA 子集,以便删除 colA 中包含 NA 的行:

> df1 <- subset(df, !is.na(colA))
> df1
   colA colB colC colAA colBB colCC
2     2    3   NA    NA     2    NA
3     3   NA    5     6    NA     3
6     3    4    9    NA    NA     8
7     9    6    8     1     2     9
8     5    1    1     7     7     9
9     6    9    2     9     9    NA
10    1    9    3     4     4     3

现在我想计算例如列长度​​和列中非 NA 值的百分比:

> length(df1$colAA)
[1] 7
> (nrow(subset(df1, !is.na(colAA)))/length(df1$colAA))*100
[1] 71.42857

在理想情况下,输出将被写入另一个数据帧,例如:

cat n perc_n
1 colAA 7     71
2 colBB 9     78
3 colCC 8     88

有什么方法可以以稍微优雅/高效的方式为所有列实现这一点?任何建议将不胜感激!

【问题讨论】:

  • Map(function(x,y) summary(y[!is.na(x)]), df[,1:3], df[, 4:6])summary 替换为您想要的任何内容。使用summary,您可以使用data.table::rbindlist(lapply(res, as.list), id="col") 来获得一张桌子...
  • 不要这样做data.frame(cbind(.)),只要data.frame(.) 会这样做。
  • @Frank:谢谢,这对我有用!如果您将您的评论重新发布为答案,我会相应地标记它。
  • @RuiBarradas:是的。我已经相应地编辑了帖子。

标签: r data.table percentage na summary


【解决方案1】:

您可以将两组列传递给Map

res = Map(function(x,y) summary(y[!is.na(x)]), df[,1:3], df[, 4:6])

由于帖子是用 data.table 标记的,我还建议制作一个类似的表格

data.table::rbindlist(lapply(res, as.list), id="col")

#     col Min. 1st Qu. Median  Mean 3rd Qu. Max. NA's
# 1: colA    1       4      6 5.400     7.0    9    2
# 2: colB    2       3      7 5.571     7.5    9    2
# 3: colC    3       4      7 6.286     8.5    9    1

您可以将summary 替换为您喜欢的返回命名向量的任何函数,并且它仍应与as.list + rbindlist 一起使用。

【讨论】:

  • 如果我用例如替换summary length,我收到以下错误消息:STRING_ELT() can only be applied to a 'character vector', not a 'NULL'。显然,输出不再符合预期的格式。有没有机会帮帮我?
  • @M.Teich 是的,它需要是一个 named 向量(至少对于这种方法),所以你可以这样做res = Map(function(x,y) c(n = length(y[!is.na(x)])), df[,1:3], df[, 4:6])。或者,您可以跳过第二步中的 as.list 并执行 res = Map(function(x,y) list(n = length(y[!is.na(x)])), df[,1:3], df[, 4:6]); rbindlist(res, id = "col")
  • 我正在尝试使您的代码适应类似的问题,我想使用aggregate 按组计算中位数。假设 A 和 B 是上例中未显示的分组变量, colA:colC 包含值(没有 NA), colAA:colCC 标识要保留的行(即删除具有 NA 的行)我试过这个:Map(function(x,y) aggregate(.~A+B,df[!is.na(y)],FUN=median), x=df[,3:5], y=df[, 6:8])。这会产生错误。有关如何正确执行此操作的任何建议?谢谢!
  • @M.Teich 我不确定。我很少使用聚合,但也许如果您发布一个新问题,其他人可以解决它。
  • 干杯,会的。
猜你喜欢
  • 2019-02-03
  • 2019-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
  • 1970-01-01
  • 2014-11-04
相关资源
最近更新 更多