【问题标题】:Calculate column-wise proportions of different elements with different denominators计算具有不同分母的不同元素的按列比例
【发布时间】:2016-02-28 20:55:17
【问题描述】:

我有一个 60 列的表,每列中的值如下:YES、NO、NA、NP。

    A   B   C
1  YES NO  NO
2  NA  NA  NA
3 YES NO  YES
4  NP  NP  NP

我需要计算多个比例,每个比例都有一个不同的分母:

示例:
YES 与 YES 和 NO 的百分比 (YES / (YES + NO))
NP 对除 NA 以外的所有人的百分比 (NP / (YES + NO + NP))
NA 对所有人的百分比 (NA / rows)

来自上述数据框的期望结果:

%YES.A  %NP.A  %NA.A  %YES.B
  100%    33%    25%    0%

到目前为止我所做的尝试:
尝试将 dplyrmutate 一起使用,但需要为 60 列中的每一列创建 7 个附加列。每个值四个,每个百分比三个。

试过revalue,但同样的问题是列太多

mydata$A.NO <- revalue(mydata$A, c("NO" = 1))  
mydata$A.YES <- revalue(mydata$A,c("YES" = 1)) 

希望有人可以指导我找到更好的解决方案或我应该阅读的任何库。

【问题讨论】:

  • 您的数据有多大?
  • 4k 行 X 144 列 (4MB)

标签: r replace dplyr


【解决方案1】:

我要做的第一步是将数据重新整形为长格式,然后按组计算百分比:

library(dplyr)
library(tidyr)

mydf %>% 
  gather(key, val) %>%
  group_by(key) %>% 
  summarise(pYes = 100*sum(val=="YES",na.rm=TRUE)/sum(val %in% c("YES","NO"),na.rm=TRUE),
            pNP = 100*sum(val=="NP",na.rm=TRUE)/sum(val %in% c("YES","NO","NP"),na.rm=TRUE),
            pNA = 100*sum(is.na(val))/n())

给出:

Source: local data frame [3 x 4]

    key  pYes      pNP   pNA
  (chr) (dbl)    (dbl) (dbl)
1     A   100 33.33333    25
2     B     0 33.33333    25
3     C    50 33.33333    25

您可以通过添加gather(percentage, val, -key) 作为最后一步,将此结果重新调整为与以下相同的格式。


您可以通过先汇总然后重新整形为长格式来做到这一点:

mydf %>% 
  summarise_each(funs(pYes = sum(.=="YES",na.rm=TRUE)/sum(.%in% c("YES","NO"),na.rm=TRUE),
                      pNP = 100*sum(.=="NP",na.rm=TRUE)/sum(. %in% c("YES","NO","NP"),na.rm=TRUE),
                      pNA = 100*sum(is.na(.))/n())) %>%
  gather(key, val) %>%
  separate(key, c("column","percentage"), sep="_")

给出:

  column percentage       val
1      A       pYes 100.00000
2      B       pYes   0.00000
3      C       pYes  50.00000
4      A        pNP  33.33333
5      B        pNP  33.33333
6      C        pNP  33.33333
7      A        pNA  25.00000
8      B        pNA  25.00000
9      C        pNA  25.00000

【讨论】:

  • 您之前的答案正是我想要的。可以应用于按数据分组吗?
  • @ErickOGM 是的,您使用 group_by
【解决方案2】:

这是在 base-R 中为您提供的解决方案。由于您只需要汇总度量,因此无需创建新列。我们只是创建一个新的摘要数据对象。

首先,我们编写一个 custum 函数来计算一个向量(列)所需的一切。我已经完成了您的两个示例,但您可以轻松扩展:

myfun <- function(x){
  res <- c(YES=sum(x=="YES",na.rm=T)/sum(x %in% c("YES","NO"),na.rm=T),
                    NP=sum(x=="NP",na.rm=T)/length(na.omit(x)))
  res
}

然后我们只需使用 lapply 将此函数应用于所有列:

res <- lapply(dat, myfun)

这为我们提供了一个向量列表(您可以在函数中轻松更改内容;您想要列表、向量、数据框还是 data.table?)

我们可以将它们组合起来:

do.call(rbind,res)
  YES        NP
A 1.0 0.3333333
B 0.0 0.3333333
C 0.5 0.3333333

【讨论】:

  • dataframe 到后面的 group_by 并在地理上总结
【解决方案3】:

将数据框转换为数据表使其速度提高了约 50%。

dt <- data.table(df)
dt[, sapply(.SD, myfun)]

df是原始数据框,myfun是Herka提供的如下函数:

myfun <- function(x){
  res <- c(YES=sum(x=="YES",na.rm=T)/sum(x %in% c("YES","NO"),na.rm=T),
                    NP=sum(x=="NP",na.rm=T)/length(na.omit(x)))
  res
}

【讨论】:

    猜你喜欢
    • 2017-09-13
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    相关资源
    最近更新 更多