2017-06-15 14 views
5

Mam dane ankietowe, w których kolumny odpowiadają pozycjom i wierszom odpowiadającym klientom, mówiącym o prawdopodobieństwie zakupu każdego przedmiotu. Wygląda to tak:Bardziej efektywny sposób na uzyskanie zliczeń częstotliwości w kolumnach ramki danych

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) 

Chcę tabeli podsumowującej podając odsetek każdej odpowiedzi dla każdej pozycji. W tej chwili używam table() na każdej kolumnie dla tego procesu i jego wiele kodu do manipulowania. Jak mogę to zrobić za pomocą plyr lub zastosować lub coś szybciej?

Aktualny rozwiązanie:

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

Uwaga I naprawdę nie trzeba liczniki FREQ, tylko procenty.

Z góry dziękuję!

+0

'lapply (DF, function (x) prop.table (tabela (x))) ' – user20650

Odpowiedz

5

Jak masz ten sam zakres wartości w każdym punkcie # można użyć

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 

Ale gdyby było inaczej można ustawić każdy element # mieć wspólny zestaw poziomów

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

Byłoby najłatwiej, jeśli spróbujesz sobie z nimi poradzić na wcześniejszym etapie.Naucząc czytanie, powiedzmy, używając 'read.table' set' na. ciągi = c ("", "") '. Lub możesz ustawić te puste wartości na brakujące' df [df == ""] <- NA' ... – user20650

+1

i usunąłem to pytanie, które sprawiło, że wyglądasz jak mówisz do sobie lol przepraszam, ale w zasadzie zrobiłem sapply (df, function (x) prop.table (table (x, exclude = ""))), aby kontrolować puste miejsca w moich danych – SarahGC

+1

Dobre rzeczy.Myślę, że lepiej jest próbuj i sortuj te rzeczy na wcześniejszym etapie, ponieważ ich rozwiązywanie stanie się trudniejsze, gdy twoja analiza stanie się bardziej skomplikowana – user20650

2

Korzystanie 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

Dzięki! Bardzo pomocne. Mam jednak wiele więcej niż 3 kolumny. Może zrobić coś takiego jak "dla (col w colnames (df)) {results = cbind (wyniki, data.frame (df%>% group_by (col) ..... " Chyba że jest lepszy sposób? – SarahGC

+0

Matt! Nie myśl, że zastosowanie może być pomocne cc: @SarahCummings – Masoud

2

Rozważmy łańcuch połączyć z Reduce gdzie najpierw pętli każdej kolumnie dataframe przez liczbę z lapply zbudować listę dataframes który jest następnie przekazywany do merge na Response:

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

Proponuję użyć innego sposobu organizowania danych, przy użyciu poziomów czynnikiem różnią przedmiotów . Ułatwia to pracę z danymi. będę przekształcić swoje dane za pomocą funkcji zbierania, a następnie użyj podsumować obliczyć procenty częstotliwość:

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 

użyłem dplyr i szczotkę do tego, ale ja wolę pomocą tidyverse biblioteki, ponieważ ładuje oba pakiety naraz .

Edycja: Jeśli chcesz użyć zachować częstotliwości jak kolumny, można użyć spread, aby to zrobić:

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 
Powiązane problemy