2016-02-28 67 views
1

我有一個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的NP的(YES/(YES + NO)
百分比針對所有除NA的( NP/(YES + NO + NP)
NA對所有的百分比(NA/rows

期望的重新SULT從上面的數據幀:

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

我迄今爲止嘗試:
嘗試使用dplyrmutate,但需要爲每個60列的創建7個aditional的列。每個價值四個,每個百分比三個。

試過revalue,但太多的列相同的問題

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

希望有人能指導我到一個更好的解決方案,或者我應該讀的任何庫。

+0

多大是你的數據? – Heroka

+0

4k行X 144 cols(4MB) – ErickOGM

回答

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 
+0

您以前的答案是我正在尋找的。它可以用數據分組嗎? – ErickOGM

+0

@ErickOGM是的,你使用了'group_by'。 – Jaap

1

以下是base-R中的解決方案。由於您只需要摘要措施,因此不需要創建新列。我們只是創建一個新的摘要數據對象。首先,我們編寫一個custum函數來計算我們需要的一個向量(列)的所有內容。我已經做了兩個你的例子,但你可以很容易地擴展:

res <- lapply(dat, myfun) 

這給了我們向量的列表(:

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此功能適用於我們所有列你可以很容易地改變周圍的事物的功能,做你想做的列表,向量,數據幀或data.table)

我們可以將它們組合起來:

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

dataframe到稍後的group_by並在地理上總結 – ErickOGM

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 
}