Dplyr के साथ सापेक्ष आवृत्तियों / अनुपात


153

मान लीजिए मैं प्रत्येक समूह के भीतर विभिन्न मूल्यों के अनुपात की गणना करना चाहता हूं। उदाहरण के लिए, का उपयोग कर mtcarsडेटा, मैं कैसे की गणना करते रिश्तेदार की संख्या की आवृत्ति गियर द्वारा बजे (स्वचालित / मैनुअल) के साथ एक ही बार में dplyr?

library(dplyr)
data(mtcars)
mtcars <- tbl_df(mtcars)

# count frequency
mtcars %>%
  group_by(am, gear) %>%
  summarise(n = n())

# am gear  n
#  0    3 15 
#  0    4  4 
#  1    4  8  
#  1    5  5 

मैं क्या हासिल करना चाहूंगा:

am gear  n rel.freq
 0    3 15      0.7894737
 0    4  4      0.2105263
 1    4  8      0.6153846
 1    5  5      0.3846154

1
क्या वे प्रतिशत आप चाहते हैं कि वास्तविक संख्या है? वे कहाँ से आ रहे हैं, बीजगणितीय रूप से? आह,, ९% १५ / (१५ + ४) है, २१% ४ / (१५ + ४) है और फिर am == १ के लिए ६२% 62 / (5 + ५) आदि है।
स्पेल्डमैन जूल

1
@Spacedman हां, वे संख्याएं हैं जो मैं चाहता हूं और फ्रैंक सही है, वे 100% योग हैं चर चर (79 + 21) और (62 + 38) द्वारा
jenswirf

2
यह वास्तव में prop.table()/ की एक देशी dplyr कार्यान्वयन के लिए लग रही है sweep()। इसके अलावा, अन्य प्रश्नों में कुछ लोग चर या चर-बातचीत के लिए शून्य-गणना को शामिल करने का विकल्प पूछ
smci

जवाबों:


285

इसे इस्तेमाल करे:

mtcars %>%
  group_by(am, gear) %>%
  summarise(n = n()) %>%
  mutate(freq = n / sum(n))

#   am gear  n      freq
# 1  0    3 15 0.7894737
# 2  0    4  4 0.2105263
# 3  1    4  8 0.6153846
# 4  1    5  5 0.3846154

Dplyr विगनेट से :

जब आप कई चर द्वारा समूह बनाते हैं, तो प्रत्येक सारांश समूह के एक स्तर को छील देता है। यह एक डेटासेट को उत्तरोत्तर रोल-अप करना आसान बनाता है।

इस प्रकार, के बाद , 'गियर' summariseमें निर्दिष्ट अंतिम समूहीकरण चर group_byको छील दिया जाता है। में mutateकदम है, डेटा शेष समूहीकरण चर (रों) द्वारा 'बजे' वर्गीकृत किया गया है, यहाँ। आप प्रत्येक चरण में समूहीकरण की जाँच कर सकते हैं groups

छीलने का परिणाम निश्चित रूप से group_byकॉल में समूह चर के क्रम पर निर्भर है । आप group_by(am)अपने कोड को और अधिक स्पष्ट करने के लिए, बाद में करने की इच्छा कर सकते हैं ।

गोलाई और पूर्व-निर्धारण के लिए, कृपया @ टायलर रिंकर द्वारा दिए गए अच्छे उत्तर को देखें।


5
मैंने अभी उस समाधान को भी खोजा है, लेकिन मुझे नहीं पता कि समूह sum(n)पर काम क्यों होता है amऔर gearसमूह का भी नहीं ...
Spacedman

7
विगनेट देखें : "जब आप कई चर द्वारा समूह बनाते हैं, तो प्रत्येक सारांश समूह के एक स्तर को छील देता है।"
हेनरिक

7
अच्छा - यदि आप summariseइसे रोकने के बाद कहते हैं कि कौन से समूह बचे हैं। ओह डस्परर चट्टानें ...
स्पेल्डमैन

सरल और स्पष्ट। मैं पहले कभी भी छिलकों को सिद्धांत से नहीं जानता था, धन्यवाद!
शिक्सियांग वांग

अच्छा। सरल और प्रभावी। अच्छा काम!
user2550228

38

आप count()फ़ंक्शन का उपयोग कर सकते हैं , जिसका संस्करण के आधार पर एक अलग व्यवहार है dplyr:

  • dplyr 0.7.1: रिटर्न एक असमूहीकृत तालिका: आपके द्वारा फिर से समूह की जरूरत हैam

  • dplyr <0.7.1: एक समूहीकृत तालिका लौटाता है , इसलिए फिर से समूह बनाने की आवश्यकता नहीं है, हालांकि आप ungroup()बाद के जोड़तोड़ के लिए चाहते हो सकते हैं

dplyr 0.7.1

mtcars %>%
  count(am, gear) %>%
  group_by(am) %>%
  mutate(freq = n / sum(n))

dplyr <0.7.1

mtcars %>%
  count(am, gear) %>%
  mutate(freq = n / sum(n))

यह एक समूहीकृत तालिका में परिणाम करता है , यदि आप इसे आगे के विश्लेषण के लिए उपयोग करना चाहते हैं, तो यह समूहीकृत विशेषता को हटाने के लिए उपयोगी हो सकता है ungroup()


1
यह dplyr0.7.1 पर एक अमान्य उत्तर लगता है । यह "am" के प्रत्येक स्तर के बजाय "गियर" पर समग्र गणना करता है।
एडविन

30

@ हेनरिक प्रयोज्यता के लिए बेहतर है क्योंकि इससे स्तंभ चरित्र और अब संख्यात्मक नहीं होगा लेकिन आपके द्वारा पूछे गए से मेल खाता है ...

mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq = paste0(round(100 * n/sum(n), 0), "%"))

##   am gear  n rel.freq
## 1  0    3 15      79%
## 2  0    4  4      21%
## 3  1    4  8      62%
## 4  1    5  5      38%

EDIT क्योंकि Spacedman ने इसके लिए कहा :-)

as.rel_freq <- function(x, rel_freq_col = "rel.freq", ...) {
    class(x) <- c("rel_freq", class(x))
    attributes(x)[["rel_freq_col"]] <- rel_freq_col
    x
}

print.rel_freq <- function(x, ...) {
    freq_col <- attributes(x)[["rel_freq_col"]]
    x[[freq_col]] <- paste0(round(100 * x[[freq_col]], 0), "%")   
    class(x) <- class(x)[!class(x)%in% "rel_freq"]
    print(x)
}

mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq = n/sum(n)) %>%
  as.rel_freq()

## Source: local data frame [4 x 4]
## Groups: am
## 
##   am gear  n rel.freq
## 1  0    3 15      79%
## 2  0    4  4      21%
## 3  1    4  8      62%
## 4  1    5  5      38%

6
आप हमेशा एक S3 "प्रतिशत" वर्ग बना सकते हैं जिसमें एक formatविधि है जो एक प्रतिशत चिह्न जोड़ता है ... #overkill
Spacedman

इसे लागू करना और भी दिलचस्प हो सकता है: stackoverflow.com/questions/13483430/…
Spacedman

क्या होगा यदि कोई इस उदाहरण में माध्य, sd और SE की गणना करेगा?
user3655531

6

यहाँ dplyr0.7.1 पर हेनरिक के समाधान को लागू करने वाला एक सामान्य कार्य है ।

freq_table <- function(x, 
                       group_var, 
                       prop_var) {
  group_var <- enquo(group_var)
  prop_var  <- enquo(prop_var)
  x %>% 
    group_by(!!group_var, !!prop_var) %>% 
    summarise(n = n()) %>% 
    mutate(freq = n /sum(n)) %>% 
    ungroup
}

Error in bind_rows_(x, .id) : Column am` को संख्यात्मक से वर्ण में परिवर्तित नहीं किया जा सकता है
f0nzie

5

मैंने इस दोहराए जाने वाले कार्य के लिए एक छोटा सा कार्य लिखा है:

count_pct <- function(df) {
  return(
    df %>%
      tally %>% 
      mutate(n_pct = 100*n/sum(n))
  )
}

मैं तब इसका उपयोग कर सकता हूं:

mtcars %>% 
  group_by(cyl) %>% 
  count_pct

यह रिटर्न:

# A tibble: 3 x 3
    cyl     n n_pct
  <dbl> <int> <dbl>
1     4    11  34.4
2     6     7  21.9
3     8    14  43.8

3

कई उत्तरों के बावजूद, एक और दृष्टिकोण जो prop.tableसंयोजन में dplyrया के साथ उपयोग करता है data.table

library("dplyr")
mtcars %>%
    group_by(am, gear) %>%
    summarise(n = n()) %>%
    mutate(freq = prop.table(n))

library("data.table")
cars_dt <- as.data.table(mtcars)
cars_dt[, .(n = .N), keyby = .(am, gear)][, freq := prop.table(n) , by = "am"]

1
अब तक का सबसे सरल तरीका है
पार्सलोंगोंग

1

यह उत्तर Matifou के उत्तर पर आधारित है।

पहले मैंने इसे यह सुनिश्चित करने के लिए संशोधित किया कि मुझे स्काइप विकल्प का उपयोग करके फ्रीक कॉलम एक वैज्ञानिक नोटेशन कॉलम के रूप में वापस नहीं मिला है।

तब मैंने फ्रीक कॉलम को प्रतिशत के रूप में पढ़ने के लिए आसान बनाने के लिए दशमलव के बजाय एक प्रतिशत प्राप्त करने के लिए 100 से अधिक उत्तर दिया।

getOption("scipen") 
options("scipen"=10) 
mtcars %>%
count(am, gear) %>% 
mutate(freq = (n / sum(n)) * 100)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.