我有一些调查数据,其中列对应于项目,而行对应于客户说明他们购买每件商品的可能性。看起来像这样:
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 :(得分: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)))
答案 1 :(得分: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
答案 2 :(得分:2)
考虑与Reduce
的链合并,您首先使用lapply
按数字循环遍历数据框的每一列,以构建数据框列表,然后将其传递到上的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
答案 3 :(得分: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和broom,但我更喜欢使用tidyverse库,因为它会同时加载两个包。
编辑:如果要使用将频率保留为列,可以使用spread来执行此操作:
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