2017-06-15 11 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を使用してこれを行うことができますか?

現在のソリューション:私は本当にFREQカウントを必要としない

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]) 

注意、ただのパーセンテージ。

ありがとうございます! dplyrを使用して

+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'を使って読み込みます。または、これらの空白の値を 'df [df ==" "] < - NA'に設定することもできます... – user20650

+1

私はあなたに話しているように見せかけたその質問を削除しました。私のデータの空白を制御するためにサプリー(df、function(x)prop.table(table(x、exclude = "")))を実行しました – SarahGC

+1

良いものです。あなたの分析がより複雑になるにつれて、それらを扱うことがより困難になるので、早い段階でこれらのことを試してみてください。 – user20650

2

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つ以上の列を持っています。あなたのためにもっと良い方法がないかぎり、 "colnames(col)のcol(result)=結果(cfind)"のようになります。 – SarahGC

+0

マット!適用が役立つと思ってはいけません。cc:@SarahCummings – Masoud

2

は、チェーンを考えてみましょうその後、レスポンスmergeに渡されるデータフレームのリストを構築するためにlapplyと数によって、データフレームの各列を通してあなた最初のループReduceと合併します:

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 
関連する問題