কীভাবে আর-তে গ্রুপ দ্বারা ডেটা সংক্ষিপ্ত করবেন? [বন্ধ]


181

আমার কাছে আর ডেটা ফ্রেম রয়েছে:

        age group
1   23.0883     1
2   25.8344     1
3   29.4648     1
4   32.7858     2
5   33.6372     1
6   34.9350     1
7   35.2115     2
8   35.2115     2
9   35.2115     2
10  36.7803     1
...

আমাকে নিম্নলিখিত ফর্মটিতে ডেটা ফ্রেম পাওয়া দরকার:

group mean     sd
1     34.5     5.6
2     32.3     4.2
...

গ্রুপ নম্বর পৃথক হতে পারে, তবে তাদের নাম এবং পরিমাণ কল করে পাওয়া যাবে levels(factor(data$group))

ফলাফল পেতে ডেটা দিয়ে কী কী হেরফের করা উচিত?


ফলাফল ডেটা ফ্রেমে কমা বলতে কিছু বিশেষ বোঝায় বা এটি কেবল দশমিক বিন্দু?
এমপিক্টাস

@ এমপিক্টাস লক্ষ করার জন্য আপনাকে ধন্যবাদ সংশোধন। এগুলি স্থানীয় সমস্যা ছিল (আমি রাশিয়ান) - আমরা দশমিক পৃথকীকরণের জন্য কমা ব্যবহার করি।
ইউরি পেট্রোভস্কি

3
আমার সন্দেহ হয়েছিল। ইউরোপের সমস্ত অংশই ব্রিটিশদের বাদ দিয়ে কমা ব্যবহার করে।
এমপিটকাস

4
ব্রিটিশ না হওয়া সত্ত্বেও আমি দশমিক বিভাজকের জন্য বিন্দুটিকে পছন্দ করি।
রোমান Luštrik

1
দেখুন aggregate, tapply, এবং তারপর stackoverflow.com এই ধরনের কোনো পরবর্তী কোডিং প্রশ্নের জন্য।
কনজুগেটপায়ার

উত্তর:


140

এখানে প্লাইডার ওয়ান লাইন ভেরিয়েন্টটি ddply ব্যবহার করে :

dt <- data.frame(age=rchisq(20,10),group=sample(1:2,20,rep=T))
ddply(dt,~group,summarise,mean=mean(age),sd=sd(age))

নতুন প্যাকেজ ডেটা টেবিল ব্যবহার করে এখানে আরও একটি লাইন বৈকল্পিক ।

dtf <- data.frame(age=rchisq(100000,10),group=factor(sample(1:10,100000,rep=T)))
dt <- data.table(dtf)
dt[,list(mean=mean(age),sd=sd(age)),by=group]

এটি দ্রুততর, যদিও এটি কেবল 100k সারি সহ টেবিলে লক্ষণীয়। 2.53 গিগাহাড কোর 2 ডুও প্রসেসর এবং আর 2.11.1 এর সাথে আমার ম্যাকবুক প্রোতে সময়গুলি:

> system.time(aa <- ddply(dtf,~group,summarise,mean=mean(age),sd=sd(age)))
utilisateur     système      écoulé 
      0.513       0.180       0.692 
> system.time(aa <- dt[,list(mean=mean(age),sd=sd(age)),by=group])
utilisateur     système      écoulé 
      0.087       0.018       0.103 

আমরা যদি ব্যবহার করি তবে আরও সঞ্চয় সম্ভব setkey:

> setkey(dt,group)
> system.time(dt[,list(mean=mean(age),sd=sd(age)),by=group])
utilisateur     système      écoulé 
      0.040       0.007       0.048 

2
@ সিএইচএল, এটি আমাকে এই নতুন ডেটা . টেবিল প্যাকেজটি চেষ্টা করার সুযোগ দিয়েছে । এটি সত্যিই আশাব্যঞ্জক মনে হচ্ছে।
এমপিটিক্স

7
ডেটা টেবিলের জন্য +6000। এটি সত্যই dpply এর চেয়ে অনেক দ্রুত, এমনকি আমার কাছে 100k এর চেয়ে ছোট ডেটাসেটেও (আমার কাছে কেবল 20k সারি রয়েছে)। আমি যে ফাংশনগুলি প্রয়োগ করছি তার সাথে অবশ্যই কিছু করা উচিত, তবে ddply কয়েক মিনিট এবং ডেটা নেবে।
পারমাণবিকগুলি

সাধারণ টাইপো: আমার ধারণা আপনি দ্বিতীয় কোড ব্লকের dt <- data.table(dtf)পরিবর্তে বোঝাতে চেয়েছিলেন dt <- data.table(dt)। এইভাবে, আপনি প্যাকেজ dtথেকে ফাংশন না করে ডেটা ফ্রেম থেকে ডেটা টেবিল তৈরি করছেন stats। আমি এটি সম্পাদনা করার চেষ্টা করেছি, তবে ছয়টি অক্ষরের অধীনে আমি সম্পাদনাগুলি করতে পারি না।
ক্রিস্টোফার বটমস

আমার (এই ক্ষেত্রে নম্র নয়) মতামত data.tableডেটা একত্রিত করার সর্বোত্তম উপায় এবং এই উত্তরটি দুর্দান্ত, তবে এখনও কেবল পৃষ্ঠকে আঁচড় দেয়। সিনট্যাক্টিক্যালি উচ্চতর হওয়া ছাড়াও এটি অত্যন্ত নমনীয় এবং এর সাথে অনেকগুলি উন্নত বৈশিষ্ট্য রয়েছে যা এতে যোগ দেয় এবং অভ্যন্তরীণ যান্ত্রিকগুলিতে জড়িত। আরও তথ্যের জন্য FAQ, গিথব পৃষ্ঠা বা কোর্সটি দেখুন।
জেনোরামা

97

এক সম্ভাবনা হ'ল সমষ্টিগত ফাংশনটি ব্যবহার করা । এই ক্ষেত্রে,

aggregate(data$age, by=list(data$group), FUN=mean)[2]

আপনাকে কাঙ্ক্ষিত ফলাফলের দ্বিতীয় কলাম দেয়।


1
আপনার স্থানীয় সহায়তা সার্ভারের সাথে লিঙ্ক করবেন না :-) +1 তবে @ স্টিফেনের প্রতিক্রিয়াতে আমার মন্তব্য দেখুন।
সিএল

ফোন করে জিনিসটি শেষ হয়েছে data.frame(group=levels(factor(data$group)),mean=(aggregate(data$age, by=list(data$group), FUN=mean)$x),sd=(aggregate(data$age, by=list(data$group), FUN=sd)$x))তবে আমি শিউর করছি না এটি সঠিক উপায়। আমি নিশ্চিত না যে তখন কী হবে তবে বাইন্ডেড কলামগুলির ফলাফলগুলি বিভিন্ন ক্রমে হবে (আমি মনে করি এটি সম্ভব)। আপনার বিরোধিতা কি?
ইউরি পেট্রোভস্কি

9
সারি @Yuriy আদেশের অপরাজিত হওয়া উচিত, কিন্তু এখানে এটা এক কলে করতে একটি উপায় aggregate():aggregate(age ~ group, data=dat, FUN = function(x) c(M=mean(x), SD=sd(x)))
lockedoff

@ লকডঅফ: আমার উত্তরটি সম্পন্ন করার জন্য আপনাকে ধন্যবাদ!
অক্টোবরে

27

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

library(dplyr)
dt <- data.frame(age=rchisq(20,10), group=sample(1:2,20, rep=T))
grp <- group_by(dt, group)
summarise(grp, mean=mean(age), sd=sd(age))

বা সমতুল্যভাবে, dplyr/ magrittrপাইপ অপারেটরটি ব্যবহার করে :

library(dplyr)
dt <- data.frame(age=rchisq(20,10), group=sample(1:2,20, rep=T))
group_by(dt, group) %>%
 summarise(mean=mean(age), sd=sd(age))

পাইপ অপারেটরের সম্পূর্ণ ব্যবহার সম্পাদনা করুন:

library(dplyr)
data.frame(age=rchisq(20,10), group=sample(1:2,20, rep=T)) %>%
  group_by(group) %>%
  summarise(mean=mean(age), sd=sd(age))

3
জন্য +1 dplyr। এটি অনেকগুলি আর কাজকে সহজ এবং এগুলির অনেকগুলি পদ্ধতি অচল করে দিয়েছে।
গ্রেগম্যাকফার্লেন

পাইপ অপারেটর সংস্করণটির সম্পূর্ণ ব্যবহার আমার পক্ষে দুর্ভাগ্যজনকভাবে কাজ করে না
dagcilibili

আপনি dplyr বা ম্যাজিট্র্ট লোড করেছেন?
বাসটিয়ান কোয়েস্ট

সমাধানের দিকে ইঙ্গিত করার জন্য আপনাকে @ ধন্যবাদ অনেক ধন্যবাদ, সংক্ষেপে ফাংশনটি পরিবর্তনের জন্য ডেকে আনা হয়েছিল যার plyrপরিবর্তে dplyrসমস্যার সৃষ্টি হচ্ছে।
dagcilibili

12

দুর্দান্ত, dplyr সমাধান যুক্ত করার জন্য ধন্যবাদ bquast!

তখন দেখা যাচ্ছে যে, dplyr এবং ডেটা টেবিল খুব কাছাকাছি থাকে:

library(plyr)
library(dplyr)
library(data.table)
library(rbenchmark)

dtf <- data.frame(age=rchisq(100000,10),group=factor(sample(1:10,100000,rep=T)))
dt <- data.table(dtf)

setkey(dt,group)

a<-benchmark(ddply(dtf,~group,plyr:::summarise,mean=mean(age),sd=sd(age)),
         dt[,list(mean=mean(age),sd=sd(age)),by=group],
         group_by(dt, group) %>% summarise(mean=mean(age),sd=sd(age) ),
         group_by(dtf, group) %>% summarise(mean=mean(age),sd=sd(age) )
)

a[, c(1,3,4)]

ডেটা.ট্যাবিলিটি এখনও দ্রুত, ডিপ্লিয়ার () দ্বারা খুব কাছাকাছিভাবে অনুসরণ করে, যা আকর্ষণীয়ভাবে ডেটা.ফ্রেমে ডেটা.ট্যাবিলের চেয়ে দ্রুত বলে মনে হয়:

                                                              test elapsed relative
1 ddply(dtf, ~group, plyr:::summarise, mean = mean(age), sd = sd(age))   1.689    4.867
2               dt[, list(mean = mean(age), sd = sd(age)), by = group]   0.347    1.000
4   group_by(dtf, group) %>% summarise(mean = mean(age), sd = sd(age))   0.369    1.063
3    group_by(dt, group) %>% summarise(mean = mean(age), sd = sd(age))   0.580    1.671

প্রথমে আমি ভেবেছিলাম আপনার সেটকে বেঞ্চমার্কে স্থানান্তরিত করা দরকার, তবে দেখা যাচ্ছে যে এটি মোটেও সময় নেয় না।
কাস্টমার

10

বিদ্যমান পরামর্শ ছাড়াও, আপনি প্যাকেজে describe.byফাংশনটি পরীক্ষা করতে চাইতে পারেন psych

এটি একটি গ্রুপিং ভেরিয়েবলের উপর ভিত্তি করে গড় এবং স্ট্যান্ডার্ড বিচ্যুতি সহ অনেকগুলি বর্ণনামূলক পরিসংখ্যান সরবরাহ করে।


এটি দুর্দান্ত, তবে লেটেক্স আইএমইতে রফতানি করা কিছুটা জটিল।
richiemorrisroe

10

আমি খুঁজে পেয়েছি ফাংশন summaryByমধ্যে doBy প্যাকেজ এই জন্য সবচেয়ে সুবিধাজনক হতে হবে:

library(doBy)

age    = c(23.0883, 25.8344, 29.4648, 32.7858, 33.6372,
           34.935,  35.2115, 35.2115,  5.2115, 36.7803)
group  = c(1, 1, 1, 2, 1, 1, 2, 2, 2, 1)
dframe = data.frame(age=age, group=group)

summaryBy(age~group, data=dframe, FUN=c(mean, sd))
# 
#   group age.mean    age.sd
# 1     1 30.62333  5.415439
# 2     2 27.10507 14.640441

9

sqldfপ্যাকেজটি ব্যবহার করুন । এটি আপনাকে ডেটা সংক্ষিপ্ত করতে এসকিউএল ব্যবহার করার অনুমতি দেয়। আপনি এটি লোড করার পরে আপনি এমন কিছু লিখতে পারেন -

sqldf('  select group,avg(age) from data group by group  ')

8

সম্পাদিত: চিএল এর পরামর্শ অনুযায়ী

আপনি যে ফাংশনটির জন্য সন্ধান করছেন তাকে "ট্যাপলি" বলা হয় যা একটি উপাদান দ্বারা নির্দিষ্ট করে গ্রুপ অনুযায়ী ফাংশন প্রয়োগ করে।

# create some artificial data
set.seed(42)
groups <- 5

agedat <- c()
groupdat <- c()

for(group in 1:groups){
    agedat <- c(agedat,rnorm(100,mean=0 + group,1/group))
    groupdat <- c(groupdat,rep(group,100))
}
dat <- data.frame("age"=agedat,"group"=factor(groupdat))

# calculate mean and stdev age per group
res <- rbind.data.frame(group=1:5, with(dat, tapply(age, group, function(x) c(mean(x), sd(x)))))
names(res) <- paste("group",1:5)
row.names(res)[2:3] <- c("mean","sd")

আমি সাধারণভাবে ব্যবহৃত সমস্ত ডেটাস্ট্রাকচার এবং পদ্ধতিগুলি ব্যাখ্যা করে একটি প্রাথমিক আর টিউটোরিয়ালটির মাধ্যমে কাজ করার পরামর্শ দিই। অন্যথায় প্রোগ্রামিংয়ের সময় আপনি প্রতি ইঞ্চি আটকে যাবেন। বিনামূল্যে উপলব্ধ সংস্থানগুলির সংগ্রহের জন্য এই প্রশ্নটি দেখুন ।


2
@ স্টেফেন +1 তবে এখানে কোনও forলুপের দরকার নেই, আপনি নিজের ডেটা ফ্রেমের ইনলাইন, আইএমও রচনা করতে পারেন। জন্য tapplyকল, ব্যবহার function(x) c(mean(x),sd(x)))এবং cbindও.পি. উভয় পরিসংখ্যান চাইলেন যেমন ফলাফল। এছাড়াও, পাতলা প্যাকেজ ddplyথেকে সহজেই এটি করতে পারে।
সিএল

@ স্টেফেন সমস্যাটি হ'ল আমার বর্ণিত টেবিলের কাঠামোটি ঠিক আমার দরকার। উপায় এবং এসডি পেতে কোনও সমস্যা নেই। সমস্যা স্ট্যাকচারের সাথে।
ইউরি পেট্রোভস্কি

@ সিএইচএল: আপনার মন্তব্যের জন্য আপনাকে ধন্যবাদ, প্লাইয়ার সম্পর্কে জানেন না :)। আমি সিবাইন্ড যুক্ত করেছি, তবে বাকী অংশটি আছরিত রেখেছি। অন্য কেউ কৃতিত্ব নিতে পারে, এই উত্তরটি আরও অনুকূল উদাহরণ হিসাবে থাকবে।
স্টিফেন

@ ইউরি: সিবিড যুক্ত হয়েছে। আপনি যদি প্রতি গ্রুপে ফাংশন প্রয়োগ করতে ইতিমধ্যে জানতেন তবে আপনি নিজের প্রশ্নের সংশোধন করতে পারেন (কেবল স্পষ্টতার জন্য;))।
স্টিফেন

@ স্টেফেন cbind("mean"=mperage,"stdev"=stperage) gives no 'group' column. Will be joining by সিবাইন্ড (গ্রুপ = স্তরগুলি (ফ্যাক্টর (ডেটা $ গ্রুপ)), "মানে" = মাইরেজ, "স্টেডিভ" = স্টপেজ) `সঠিক?
ইউরি পেট্রোভস্কি

7

aggregates()কিছুক্ষণ আগে আমি নিজে করা ফাংশনটির একটি উদাহরণ এখানে দিয়েছি:

# simulates data
set.seed(666)
( dat <- data.frame(group=gl(3,6), level=factor(rep(c("A","B","C"), 6)), 
                    y=round(rnorm(18,10),1)) )

> dat
   group level    y
1      1     A 10.8
2      1     B 12.0
3      1     C  9.6
4      1     A 12.0
5      1     B  7.8
6      1     C 10.8
7      2     A  8.7
8      2     B  9.2
9      2     C  8.2
10     2     A 10.0
11     2     B 12.2
12     2     C  8.2
13     3     A 10.9
14     3     B  8.3
15     3     C 10.1
16     3     A  9.9
17     3     B 10.9
18     3     C 10.3

# aggregates() function
aggregates <- function(formula, data=NULL, FUNS){ 
    if(class(FUNS)=="list"){ 
        f <- function(x) sapply(FUNS, function(fun) fun(x)) 
    }else{f <- FUNS} 
    temp <- aggregate(formula, data, f) 
    out <- data.frame(temp[,-ncol(temp)], temp[,ncol(temp)]) 
    colnames(out)[1] <- colnames(temp)[1] 
return(out) 
} 

# example 
FUNS <- function(x) c(mean=round(mean(x),0), sd=round(sd(x), 0)) 
( ag <- aggregates(y~group:level, data=dat, FUNS=FUNS) ) 

এটি নিম্নলিখিত ফলাফল দেয়:

> ag
  group level mean sd
1     1     A   11  1
2     2     A    9  1
3     3     A   10  1
4     1     B   10  3
5     2     B   11  2
6     3     B   10  2
7     1     C   10  1
8     2     C    8  0
9     3     C   10  0

আর ফাংশন বিভাজন () থেকে শুরু করে আপনি একই ফলাফল পেতে পারেন:

> with(dat, sapply( split(y, group:level), FUNS ) )
     1:A 1:B 1:C 2:A 2:B 2:C 3:A 3:B 3:C
mean  11  10  10   9  11   8  10  10  10
sd     1   3   1   1   2   0   1   2   0

আমি aggregatesফাংশনটির আউটপুট ফিরে আসি । ব্যবহার করে আপনি একটি সুন্দর টেবিল এটা রুপান্তর করতে পারেন reshape(), xtabs()এবং ftable():

rag <- reshape(ag, varying=list(3:4), direction="long", v.names="y") 
rag$time <- factor(rag$time) 
ft <- ftable(xtabs(y~group+level+time, data=rag)) 
attributes(ft)$col.vars <- list(c("mean","sd")) 

এটি দেয়:

> ft 
             mean sd
group level         
1     A        11  1
      B        10  3
      C        10  1
2     A         9  1
      B        11  2
      C         8  0
3     A        10  1
      B        10  2
      C        10  0

সুন্দরী, তাই না? আপনি এই টেবিলটি প্যাকেজের textplot()কার্যকারিতা সহ একটি পিডিএফ রফতানি করতে পারেন cangplots

অন্যের সমাধানের জন্য এখানে দেখুন ।

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