গোষ্ঠী অনুসারে কীভাবে ভেরিয়েবলের যোগফল হয়


357

আমার কাছে দুটি কলাম সহ একটি ডেটা ফ্রেম রয়েছে। প্রথম কলামে "প্রথম", "দ্বিতীয়", "তৃতীয়" এর মতো বিভাগগুলি রয়েছে এবং দ্বিতীয় কলামে এমন সংখ্যা রয়েছে যা "বিভাগ" থেকে নির্দিষ্ট গোষ্ঠীগুলিকে আমি যে বার দেখেছি তার প্রতিনিধিত্ব করে।

উদাহরণ স্বরূপ:

Category     Frequency
First        10
First        15
First        5
Second       2
Third        14
Third        20
Second       3

আমি বিভাগ অনুসারে ডেটা বাছাই করতে এবং সমস্ত ফ্রিকোয়েন্সি যোগ করতে চাই:

Category     Frequency
First        30
Second       5
Third        34

আমি আর এ কিভাবে করব?


1
বেস আর দ্রুততম উপায় rowsum
মাইকেল এম

উত্তর:


387

ব্যবহার aggregate:

aggregate(x$Frequency, by=list(Category=x$Category), FUN=sum)
  Category  x
1    First 30
2   Second  5
3    Third 34

উপরের উদাহরণে, একাধিক মাত্রা এর মধ্যে নির্দিষ্ট করা যেতে পারে list। একই ডাটা টাইপের একাধিক একত্রিত মেট্রিকগুলি এর মাধ্যমে সংযুক্ত করা যেতে পারে cbind:

aggregate(cbind(x$Frequency, x$Metric2, x$Metric3) ...

(এম্বেড @ থেইলেটমেল মন্তব্য) aggregateএর একটি সূত্র ইন্টারফেসও রয়েছে

aggregate(Frequency ~ Category, x, sum)

বা যদি আপনি একাধিক কলামগুলি একত্রিত করতে চান তবে আপনি .স্বরলিপিটি ব্যবহার করতে পারেন (একটি কলামের জন্যও কাজ করে)

aggregate(. ~ Category, x, sum)

বা tapply:

tapply(x$Frequency, x$Category, FUN=sum)
 First Second  Third 
    30      5     34 

এই ডেটা ব্যবহার করে:

x <- data.frame(Category=factor(c("First", "First", "First", "Second",
                                      "Third", "Third", "Second")), 
                    Frequency=c(10,15,5,2,14,20,3))

4
@ অ্যান্ড্রুম্যাককিলে, আর সংক্ষিপ্ত সূত্রগুলি সংজ্ঞায়িত করতে টিলড ব্যবহার করে, পরিসংখ্যান এবং অন্যান্য কার্যাদি জন্য। এটি "বিভাগ দ্বারা মডেল ফ্রিকোয়েন্সি" বা "বিভাগের উপর ভিত্তি করে ফ্রিকোয়েন্সি " হিসাবে ব্যাখ্যা করা যেতে পারে । এখানে আর-তে যেমন প্রতীকী ফাংশন সংজ্ঞায়িত করতে সমস্ত ভাষা কোনও বিশেষ অপারেটর ব্যবহার করে না। সম্ভবত টিল্ড অপারেটরের সেই "প্রাকৃতিক-ভাষা ব্যাখ্যা" দিয়ে এটি আরও অর্থবহ (এবং স্বজ্ঞাত) হয়ে ওঠে। আমি ব্যক্তিগতভাবে এই প্রতীকী সূত্রের উপস্থাপনাকে আরও কিছু ভার্বোজ বিকল্পের চেয়ে ভাল বলে মনে করি।
r2evans

1
আর-তে নতুন হওয়ার কারণে (এবং ওপি হিসাবে একই ধরণের প্রশ্ন জিজ্ঞাসা করা), আমি প্রতিটি বিকল্পের পেছনের সিনট্যাক্সের আরও কিছু বিশদ থেকে উপকৃত হব। উদাহরণস্বরূপ, যদি আমার আরও বৃহত উত্স টেবিল থাকে এবং মাত্র দুটি মাত্রা প্লাস সমষ্টিযুক্ত মেট্রিকগুলি উপশম করতে চান, তবে আমি কি এই পদ্ধতির কোনওটি মানিয়ে নিতে পারি? বলা কঠিন.
ডডিকাফোন

236

আপনি সেই উদ্দেশ্যে dplyr প্যাকেজটি ব্যবহার করতে পারেন :

library(dplyr)
x %>% 
  group_by(Category) %>% 
  summarise(Frequency = sum(Frequency))

#Source: local data frame [3 x 2]
#
#  Category Frequency
#1    First        30
#2   Second         5
#3    Third        34

বা, একাধিক সংক্ষিপ্ত কলামগুলির জন্য (একটি কলামের সাথেও কাজ করে):

x %>% 
  group_by(Category) %>% 
  summarise_all(funs(sum))

বিল্ট-ইন ডেটাসেট ব্যবহার করে ডিপিপ্লায়ার ফাংশনগুলি ব্যবহার করে কীভাবে গ্রুপের মাধ্যমে ডেটা সংক্ষিপ্ত করতে হয় তার আরও কয়েকটি উদাহরণ এখানে রয়েছে mtcars:

# several summary columns with arbitrary names
mtcars %>% 
  group_by(cyl, gear) %>%                            # multiple group columns
  summarise(max_hp = max(hp), mean_mpg = mean(mpg))  # multiple summary columns

# summarise all columns except grouping columns using "sum" 
mtcars %>% 
  group_by(cyl) %>% 
  summarise_all(sum)

# summarise all columns except grouping columns using "sum" and "mean"
mtcars %>% 
  group_by(cyl) %>% 
  summarise_all(funs(sum, mean))

# multiple grouping columns
mtcars %>% 
  group_by(cyl, gear) %>% 
  summarise_all(funs(sum, mean))

# summarise specific variables, not all
mtcars %>% 
  group_by(cyl, gear) %>% 
  summarise_at(vars(qsec, mpg, wt), funs(sum, mean))

# summarise specific variables (numeric columns except grouping columns)
mtcars %>% 
  group_by(gear) %>% 
  summarise_if(is.numeric, funs(mean))

%>%অপারেটর সহ আরও তথ্যের জন্য, dplyr এর পরিচিতি দেখুন ।


1
অন্যান্য উত্তরে উপস্থাপিত ডেটা.টেল এবং সামগ্রিক বিকল্পগুলির সাথে তুলনা করলে এটি কতটা দ্রুত?
asieira

5
@ এসিইরা, কোনটি দ্রুত এবং কত বড় তফাত (বা পার্থক্যটি লক্ষণীয় হয়) সর্বদা আপনার ডেটা আকারের উপর নির্ভর করবে। সাধারণত, বড় ডেটা সেটগুলির জন্য, উদাহরণস্বরূপ কিছু জিবি, ডেটা.ট্যাবলটি সম্ভবত দ্রুততম হবে। ছোট ডেটা আকারে, ডেটা.ট্যাবলেট এবং ডিপিপ্লায়ার প্রায়শই কাছাকাছি থাকে, এছাড়াও গ্রুপের সংখ্যার উপর নির্ভর করে। উভয় ডেটা, টেবিল এবং ডিপিপ্লায়ার বেস ফাংশনগুলির তুলনায় অনেক দ্রুত হবে তবে (কিছু ক্রিয়াকলাপের জন্য 100-1000 গুণ দ্রুত হতে পারে)। এছাড়াও এখানে দেখুন
23:15

1
"মজাদার" দ্বিতীয় উদাহরণে কী বোঝায়?
লরেন.মারিটা

@ lauren.marietta আপনি ফাংশন (গুলি) নির্দিষ্ট করতে পারেন আপনি ভিতরে সারসংক্ষেপ যেমন প্রয়োগ করতে চান funs()আর্গুমেন্ট summarise_allএবং তার সংশ্লিষ্ট ফাংশন ( summarise_at, summarise_if)
তালাত

76

আরসিএসের দেওয়া উত্তরটি কাজ করে এবং সহজ। তবে, আপনি যদি আরও বড় ডেটাসেট পরিচালনা করছেন এবং পারফরম্যান্স বুস্টের প্রয়োজন হয় তবে একটি দ্রুত বিকল্প আছে:

library(data.table)
data = data.table(Category=c("First","First","First","Second","Third", "Third", "Second"), 
                  Frequency=c(10,15,5,2,14,20,3))
data[, sum(Frequency), by = Category]
#    Category V1
# 1:    First 30
# 2:   Second  5
# 3:    Third 34
system.time(data[, sum(Frequency), by = Category] )
# user    system   elapsed 
# 0.008     0.001     0.009 

ডেটা.ফ্রেম এবং উপরের উপরেরটি ব্যবহার করে এটি একই জিনিসটির সাথে তুলনা করা যাক:

data = data.frame(Category=c("First","First","First","Second","Third", "Third", "Second"),
                  Frequency=c(10,15,5,2,14,20,3))
system.time(aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum))
# user    system   elapsed 
# 0.008     0.000     0.015 

এবং আপনি যদি কলামটি রাখতে চান তবে এটি সিনট্যাক্স:

data[,list(Frequency=sum(Frequency)),by=Category]
#    Category Frequency
# 1:    First        30
# 2:   Second         5
# 3:    Third        34

নীচের কোডটি যেমন দেখিয়েছে তত বড় পার্থক্য সহ পার্থক্য আরও লক্ষণীয় হয়ে উঠবে:

data = data.table(Category=rep(c("First", "Second", "Third"), 100000),
                  Frequency=rnorm(100000))
system.time( data[,sum(Frequency),by=Category] )
# user    system   elapsed 
# 0.055     0.004     0.059 
data = data.frame(Category=rep(c("First", "Second", "Third"), 100000), 
                  Frequency=rnorm(100000))
system.time( aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum) )
# user    system   elapsed 
# 0.287     0.010     0.296 

একাধিক জমায়েতের জন্য, আপনি একত্রিত করতে পারেন lapplyএবং নীচের .SDহিসাবে

data[, lapply(.SD, sum), by = Category]
#    Category Frequency
# 1:    First        30
# 2:   Second         5
# 3:    Third        34

13
+1 তবে 0.296 বনাম 0.059 বিশেষ চিত্তাকর্ষক নয়। ডেটা.টেল টাইট করার জন্য ডেটা আকার 300k সারিগুলির চেয়ে বেশি এবং 3 টিরও বেশি গ্রুপের হওয়া দরকার। উদাহরণস্বরূপ আমরা 2 বিলিয়নেরও বেশি সারি চেষ্টা করব এবং সমর্থন করব, যেহেতু কিছু ডেটা.ট্যাবল ব্যবহারকারীদের 250 গিগাবাইট র‌্যাম রয়েছে এবং জিএনইউ আর এখন দৈর্ঘ্য> 2 ^ 31 সমর্থন করে।
ম্যাট ডাউল

2
সত্য। দেখা যাচ্ছে যে আমার কাছে এমন সমস্ত র‌্যাম নেই তবে কেবল ডেটা.টবেলের উচ্চতর পারফরম্যান্সের কিছু প্রমাণ দেওয়ার চেষ্টা করছিলাম। আমি নিশ্চিত যে আরও বেশি ডেটা সহ পার্থক্য আরও বড় হবে।
asieira

1
আমার 7 মিল পর্যবেক্ষণ dplyr .3 সেকেন্ড সময় নিয়েছে এবং সামগ্রিক () অপারেশন শেষ করতে 22 সেকেন্ড সময় নিয়েছিল। আমি এই বিষয়ে এটি পোস্ট করতে যাচ্ছিল এবং আপনি আমাকে এটি মারধর!
জাজু

3
এটি লেখার একটি আরও ছোট উপায় আছে data[, sum(Frequency), by = Category]। ফাংশনটি .Nবিকল্প হিসাবে ব্যবহার করতে পারে sum()data[, .N, by = Category]। এখানে একটি দরকারী চিটশিটটি রয়েছে
স্টোফফেস

3
.N ব্যবহার করা কেবলমাত্র ফ্রিকোয়েন্সি কলামের সমস্ত মান 1 এর সমান হলে সমষ্টি (ফ্রিকোয়েন্সি) এর সমতুল্য হবে, কারণ .N প্রতিটি সংযুক্ত সেটে (.SD) সারিগুলির সংখ্যা গণনা করে। এবং এখানে মামলা হয় না।
asieira

41

আপনি বাই () ফাংশনটিও ব্যবহার করতে পারেন :

x2 <- by(x$Frequency, x$Category, sum)
do.call(rbind,as.list(x2))

এই অন্যান্য প্যাকেজগুলির (প্লাইর, পুনঃসারণ) একটি ডেটা.ফ্রেম ফিরিয়ে দেওয়ার সুবিধা রয়েছে তবে এটি একটি বেস ফাংশন হওয়ার কারণে এটি () দ্বারা পরিচিত হওয়ার মতো।


28

বেশ কয়েক বছর পরে, কেবলমাত্র অন্য একটি সাধারণ বেস আর সমাধান যুক্ত করতে যা এখানে কোনও কারণে উপস্থিত নেই- xtabs

xtabs(Frequency ~ Category, df)
# Category
# First Second  Third 
#    30      5     34 

অথবা আপনি যদি data.frameফিরে চান

as.data.frame(xtabs(Frequency ~ Category, df))
#   Category Freq
# 1    First   30
# 2   Second    5
# 3    Third   34


23

যদি xআপনার ডেটা সহ ডেটাফ্রেম হয় তবে নিম্নলিখিতগুলি আপনি যা চান তা করবে:

require(reshape)
recast(x, Category ~ ., fun.aggregate=sum)

19

যদিও আমি সম্প্রতি dplyrএই ধরণের বেশিরভাগ অপারেশনের জন্য কনভার্ট হয়ে গিয়েছি , sqldfপ্যাকেজটি এখনও কিছু জিনিসের জন্য সত্যিই দুর্দান্ত (এবং আইএমএইচও আরও পঠনযোগ্য) রয়েছে।

এই প্রশ্নের উত্তর কীভাবে দেওয়া যেতে পারে তার উদাহরণ এখানে sqldf

x <- data.frame(Category=factor(c("First", "First", "First", "Second",
                                  "Third", "Third", "Second")), 
                Frequency=c(10,15,5,2,14,20,3))

sqldf("select 
          Category
          ,sum(Frequency) as Frequency 
       from x 
       group by 
          Category")

##   Category Frequency
## 1    First        30
## 2   Second         5
## 3    Third        34

18

কেবল একটি তৃতীয় বিকল্প যুক্ত করতে:

require(doBy)
summaryBy(Frequency~Category, data=yourdataframe, FUN=sum)

সম্পাদনা: এটি একটি খুব পুরানো উত্তর। এখন আমি @ অ্যাসেন্ডো উত্তর হিসাবে, এর থেকে group_byএবং এর ব্যবহারের পরামর্শ দেব ।summarisedplyr


7

আমি আপনাকে aveখুব সহায়ক (এবং দক্ষ) পেয়েছি যখন যখন আপনাকে বিভিন্ন কলামগুলিতে বিভিন্ন একীকরণ ফাংশন প্রয়োগ করতে হবে (এবং আপনাকে অবশ্যই বেস বেসটি আটকে রাখতে চান):

যেমন

এই ইনপুট দেওয়া:

DF <-                
data.frame(Categ1=factor(c('A','A','B','B','A','B','A')),
           Categ2=factor(c('X','Y','X','X','X','Y','Y')),
           Samples=c(1,2,4,3,5,6,7),
           Freq=c(10,30,45,55,80,65,50))

> DF
  Categ1 Categ2 Samples Freq
1      A      X       1   10
2      A      Y       2   30
3      B      X       4   45
4      B      X       3   55
5      A      X       5   80
6      B      Y       6   65
7      A      Y       7   50

আমরা গ্রুপে দ্বারা চান Categ1এবং Categ2এবং এর সমষ্টি গনা Samplesএবং অর্থ Freq
এখানে একটি সম্ভাব্য সমাধান ব্যবহার করে ave:

# create a copy of DF (only the grouping columns)
DF2 <- DF[,c('Categ1','Categ2')]

# add sum of Samples by Categ1,Categ2 to DF2 
# (ave repeats the sum of the group for each row in the same group)
DF2$GroupTotSamples <- ave(DF$Samples,DF2,FUN=sum)

# add mean of Freq by Categ1,Categ2 to DF2 
# (ave repeats the mean of the group for each row in the same group)
DF2$GroupAvgFreq <- ave(DF$Freq,DF2,FUN=mean)

# remove the duplicates (keep only one row for each group)
DF2 <- DF2[!duplicated(DF2),]

ফলাফল :

> DF2
  Categ1 Categ2 GroupTotSamples GroupAvgFreq
1      A      X               6           45
2      A      Y               9           40
3      B      X               7           50
6      B      Y               6           65

6

সম্প্রতি যুক্ত হওয়া dplyr::tally()এটিকে আগের চেয়ে সহজ করে তুলেছে:

tally(x, Category)

Category     n
First        30
Second       5
Third        34

6

আপনি প্যাকেজ রাস্তাgroup.sum থেকে ফাংশনটি ব্যবহার করতে পারেন ।

Category <- Rfast::as_integer(Category,result.sort=FALSE) # convert character to numeric. R's as.numeric produce NAs.
result <- Rfast::group.sum(Frequency,Category)
names(result) <- Rfast::Sort(unique(Category)
# 30 5 34

প্রাতঃরাশের অনেকগুলি গ্রুপ ফাংশন রয়েছে এবং সেগুলিরgroup.sum মধ্যে একটি।


4

castপরিবর্তে ব্যবহার recast(নোট 'Frequency'এখন 'value')

df  <- data.frame(Category = c("First","First","First","Second","Third","Third","Second")
                  , value = c(10,15,5,2,14,20,3))

install.packages("reshape")

result<-cast(df, Category ~ . ,fun.aggregate=sum)

পেতে:

Category (all)
First     30
Second    5
Third     34

2

আর একটি সমাধান যা ম্যাট্রিক্স বা ডেটা ফ্রেমে গ্রুপ দ্বারা অঙ্কগুলি ফেরত দেয় এবং সংক্ষিপ্ত এবং দ্রুত:

rowsum(x$Frequency, x$Category)

সুন্দরভাবে এবং সত্যিই দ্রুত।
jay.sf
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.