计算具有不同分母的不同元素的列式比例

时间:2016-02-28 20:55:18

标签: r replace dplyr

我有一个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和NO(YES / (YES + NO))的YES的百分比为
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)) 

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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

以下是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

答案 2 :(得分:1)

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

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

df是原始数据框,myfun是Heroka提供的以下功能:

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
}