2017-06-15 36 views
5

我有一些調查數據,其中列對應的項目和行對應於客戶說他們有多大可能購買每個項目。看起來像這樣:更有效的方法來獲得跨數據幀的列頻率計數

item1 = c("Likely", "Unlikely", "Very Likely","Likely") 
item2 = c("Likely", "Unlikely", "Very Likely","Unlikely") 
item3 = c("Very Likely", "Unlikely", "Very Likely","Likely") 
df = data.frame(item1, item2, item3) 

我想要一個總結表給出每個項目的每個響應的百分比。現在我在這個過程的每一列上都使用了table(),並且有很多代碼需要處理。我該如何使用plyr來做到這一點,或更快地應用或更快?

目前的解決方案:

d1<-as.data.frame(table(df$item1)) 
d1$item1_percent<- d1$Freq/sum(d1$Freq) 
names(d1)<-c("Response","item1_freqs","item1_percent") 

d2<-as.data.frame(table(df$item2)) 
d2$item2_percent<- d2$Freq/sum(d2$Freq) 
names(d2)<-c("Response","item2_freqs","item2_percent") 

d3<-as.data.frame(table(df$item3)) 
d3$item3_percent<- d3$Freq/sum(d3$Freq) 
names(d3)<-c("Response","item3_freqs","item3_percent") 

results<-cbind(d1,d2[,2:3],d3[,2:3]) 

注意我並不真正需要的頻率計數,只是百分比。

提前致謝!

+0

'lapply(DF,函數(X)prop.table(表(X))) ' – user20650

回答

5

正如你在每個項目相同的值範圍#你可以使用

sapply(df, function(x) prop.table(table(x))) 
#    item1 item2 item3 
# Likely  0.50 0.25 0.25 
# Unlikely  0.25 0.50 0.25 
# Very Likely 0.25 0.25 0.50 

但是,如果他們是不同的,你可以設置每個項目#有一個共同的一系列級別

df[] <- lapply(df, factor, levels=unique(unlist(df))) 
sapply(df, function(x) prop.table(table(x))) 
+0

如果您嘗試在早期階段處理這些問題,最簡單的方法是使用'read.table'設置'na。字符串= c(「」,「」)'。或者你可以設置這些空白值缺少'df [df ==「」] < - NA' ... – user20650

+1

我刪除了那個讓你看起來像你在說話的問題自己哈哈對不起。但基本上我做了sapply(df,function(x)prop.table(table(x,exclude =「」)))來控制我的數據中的空白 – SarahGC

+1

好東西,我認爲這樣更好儘管在早期階段嘗試和排序這些東西,因爲隨着分析變得越來越複雜,處理它們會變得更加困難 – user20650

2

使用dplyr

results = data.frame(df %>% 
        group_by(item1) %>% 
          summarise(no_rows=length(item1)/nrow(df))) 
results = cbind(results, 
      data.frame(df %>% 
        group_by(item2) %>% 
          summarise(no_rows=length(item2)/nrow(df)))) 

results = cbind(results, 
      data.frame(df %>% 
        group_by(item3) %>% 
          summarise(no_rows=length(item3)/nrow(df)))) 


# > results 
#  item1 no_rows  item2 no_rows  item3 no_rows 
# 1  Likely 0.50  Likely 0.25  Likely 0.25 
# 2 Unlikely 0.25 Unlikely 0.50 Unlikely 0.25 
# 3 Very Likely 0.25 Very Likely 0.25 Very Likely 0.50 
+0

謝謝!很有幫助。不過,我有不止3列。可能會做一些類似於「for col(colnames(df)){results = cbind(results,data.frame(df%>%group_by(col)..... 」除非是更好的方法嗎? – SarahGC

+0

Matt!不要認爲應用可能會有所幫助。cc:@SarahCummings – Masoud

2

考慮鏈Reduce合併,其中通過數據幀的每一列與lapply你第一次循環來構建dataframes被然後響應傳遞到merge的列表:

dfList <- lapply(seq_along(df), function(i){  
    d <- as.data.frame(table(df[,i])) 
    d$item1_percent <- d$Freq/sum(d$Freq) 
    # PASS COLUMN NUMBER INTO DF COLUMN NAMES 
    names(d) <- c("Response", paste0("item",i,"_freqs"), paste0("item",i,"_percent")) 

    return(d)  
}) 

results2 <- Reduce(function(x,y) merge(x, y, by="Response", all.equal=TRUE), dfList) 

# EQUIVALENT TO ORIGINAL results 
all.equal(results, results2) 
# [1] TRUE 
identical(results, results2) 
# [1] TRUE 
2

我會建議使用組織數據的方式不同,採用因子水平不同的項目。這使得處理數據變得很容易。我將使用收集功能轉換數據,然後使用匯總計算頻率百分比:

library(tidyverse) 

results <- df %>% 
gather("item", "likelihood") %>% 
group_by(item, likelihood) %>% 
summarise(n = n()) %>% 
mutate(freq = n/sum(n)) 

# > results 
# A tibble: 9 x 4 
# Groups: item [3] 
# item likelihood  n freq 
# <chr>  <chr> <int> <dbl> 
# 1 item1  Likely  2 0.50 
# 2 item1 Unlikely  1 0.25 
# 3 item1 Very Likely  1 0.25 
# 4 item2  Likely  1 0.25 
# 5 item2 Unlikely  2 0.50 
# 6 item2 Very Likely  1 0.25 
# 7 item3  Likely  1 0.25 
# 8 item3 Unlikely  1 0.25 
# 9 item3 Very Likely  2 0.50 

我用dplyr和掃帚對於這一點,但我更喜歡使用tidyverse庫,因爲它加載這兩個程序包一次。

編輯:如果你想使用保持頻率爲列,您可以使用傳播這樣做:

col_results <- results %>% 
    select(-n) %>% 
    spread(item, freq) 

# > col_results 
# A tibble: 3 x 4 
# likelihood item1 item2 item3 
# *  <chr> <dbl> <dbl> <dbl> 
# 1  Likely 0.50 0.25 0.25 
# 2 Unlikely 0.25 0.50 0.25 
# 3 Very Likely 0.25 0.25 0.50 
相關問題