سؤال
لدي إطار بيانات يحتوي على 900000 صف و 11 عمودًا في R. أسماء الأعمدة والأنواع هي كما يلي:
column name: date / mcode / mname / ycode / yname / yissue / bsent / breturn / tsent / treturn / csales
type: Date / Char / Char / Char / Char / Numeric / Numeric / Numeric / Numeric / Numeric / Numeric
أريد حساب المجاميع الفرعية. على سبيل المثال ، أريد حساب المبالغ في كل تغيير في yname ، وإضافة المجموع الفرعي إلى جميع المتغيرات العددية. هناك 160 ynames متميزة ، لذلك يجب أن يخبرني الجدول الناتج عن المجموع الفرعي لكل yname. لم أفرز البيانات بعد ، لكن هذه ليست مشكلة لأنه يمكنني فرز البيانات بأي طريقة أريدها. فيما يلي مقتطف من بياناتي:
date mcode mname ycode yname yissue bsent breturn tsent treturn csales
417572 2010-07-28 45740 ENDPOINT A 5772 XMAG 20100800 7 0 7 0 0
417573 2010-07-31 45740 ENDPOINT A 5772 XMAG 20100800 0 0 0 0 1
417574 2010-08-04 45740 ENDPOINT A 5772 XMAG 20100800 0 0 0 0 1
417575 2010-08-14 45740 ENDPOINT A 5772 XMAG 20100800 0 0 0 0 1
417576 2010-08-26 45740 ENDPOINT A 5772 XMAG 20100800 0 4 0 0 0
417577 2010-07-28 45741 ENDPOINT L 5772 XMAG 20100800 2 0 2 0 0
417578 2010-08-04 45741 ENDPOINT L 5772 XMAG 20100800 2 0 2 0 0
417579 2010-08-26 45741 ENDPOINT L 5772 XMAG 20100800 0 4 0 0 0
417580 2010-07-28 46390 ENDPOINT R 5772 XMAG 20100800 3 0 3 0 1
417581 2010-07-29 46390 ENDPOINT R 5772 XMAG 20100800 0 0 0 0 2
417582 2010-08-01 46390 ENDPOINT R 5779 YMAG 20100800 3 0 3 0 0
417583 2010-08-11 46390 ENDPOINT R 5779 YMAG 20100800 0 0 0 0 1
417584 2010-08-20 46390 ENDPOINT R 5779 YMAG 20100800 0 0 0 0 1
417585 2010-08-24 46390 ENDPOINT R 5779 YMAG 20100800 2 0 2 0 1
417586 2010-08-26 46390 ENDPOINT R 5779 YMAG 20100800 0 2 0 2 0
417587 2010-07-28 46411 ENDPOINT D 5779 YMAG 20100800 6 0 6 0 0
417588 2010-08-08 46411 ENDPOINT D 5779 YMAG 20100800 0 0 0 0 1
417589 2010-08-11 46411 ENDPOINT D 5779 YMAG 20100800 0 0 0 0 1
417590 2010-08-26 46411 ENDPOINT D 5779 YMAG 20100800 0 4 0 4 0
ما هي الوظيفة التي يجب أن أستخدمها هنا؟ ربما شيء مثل SQL group by
?
المحلول
نعم. على افتراض أن بياناتك في إطار بيانات مسمى foo
:
> head(foo)
date mcode mname ycode yname yissue bsent breturn tsent
417572 2010/07/28 45740 ENDPOINT A 5772 XMAG 20100800 7 0 7
417573 2010/07/31 45740 ENDPOINT A 5772 XMAG 20100800 0 0 0
417574 2010/08/04 45740 ENDPOINT A 5772 XMAG 20100800 0 0 0
417575 2010/08/14 45740 ENDPOINT A 5772 XMAG 20100800 0 0 0
417576 2010/08/26 45740 ENDPOINT A 5772 XMAG 20100800 0 4 0
417577 2010/07/28 45741 ENDPOINT L 5772 XMAG 20100800 2 0 2
treturn csales
417572 0 0
417573 0 1
417574 0 1
417575 0 1
417576 0 0
417577 0 0
ثم سيؤدي ذلك إلى تجميع الأعمدة الرقمية في بياناتك:
> aggregate(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data = foo,
+ FUN = sum)
yname bsent breturn tsent treturn csales
1 XMAG 14 8 14 0 6
2 YMAG 11 6 11 6 5
كان ذلك يستخدم مقتطف البيانات الذي قمت بتضمينه في Q. لقد استخدمت واجهة الصيغة إلى aggregate()
, ، وهو أجمل بعض الشيء في هذه الحالة لأنك لا تحتاج إلى كل foo$
بت على الأسماء المتغيرة التي تتمنى الإجمالي. إذا كان لديك بيانات مفقودة (NA
) في مجموعة البيانات الكاملة ، ستحتاج إلى إضافة وسيطة إضافية na.rm = TRUE
التي سيتم نقلها إلى sum()
, ، مثل ذلك:
> aggregate(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data = foo,
+ FUN = sum, na.rm = TRUE)
نصائح أخرى
أو ال plyr
المكتبة ، التي يمكن توسيعها بسهولة لفئات البيانات الأخرى:
> library(plyr)
> result.2 <- ddply(df$a, .(df$b), sum)
> result.2
df.b V1
1 down 30
2 up 25
تستطيع ايضا استخذام xtabs
أو tapply
:
xtabs(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data)
tapply(data$bsent, data$yname, sum)
إذا كانت بياناتك كبيرة وسرعة السرعة ، فإنني أوصي باستخدام Rowsum R دالة R ، وهو أسرع بكثير. لقد قمت بتطبيق الأساليب الثلاثة (F1 = الركام ، f2 = ddply ، f3 = tapply) المقترحة في الإجابات لمقارنتها مع f4 = rowsum وهنا هو ما أجده:
test replications elapsed relative
4 f4() 100 0.033 1.00
3 f3() 100 0.046 1.39
1 f1() 100 0.165 5.00
2 f2() 100 0.605 18.33
لقد أضفت الكود الخاص بي أدناه إذا أراد شخص ما الاستكشاف بمزيد من التفصيل.
library(plyr);
library(rbenchmark);
val = rnorm(50);
name = rep(letters[1:5], each = 10);
data = data.frame(val, name);
f1 = function(){aggregate(data$val, by=list(data$name), FUN=sum)}
f2 = function(){ddply(data, .(name), summarise, sum = sum(val))}
f3 = function(){tapply(data$val, data$name, sum)}
f4 = function(){rowsum(x = data$val, group = data$name)}
benchmark(f1(), f2(), f3(), f4(),
columns=c("test", "replications", "elapsed", "relative"),
order="relative", replications=100)
يمكنك استخدام aggregate
على سبيل المثال ، قل أن لديك
val = rnorm(50)
name = rep(letters[1:5], each=10)
data <- data.frame(val, name)
ثم يمكنك القيام به
aggregate(data$val, by=list(data$name), FUN=sum)
هناك حزمة R تسمى SQLDF تمكنك من استخدام أوامر SQL على بيانات R Data. إلى جانب كما قلت بالفعل ، ستكون المجموعة لطيفة. يمكنك بسهولة تخزين بياناتك في قاعدة بيانات MySQL المحلية والاتصال بـ R باستخدام الحزمة RMYSQL (يمكنك استخدام معظم DBMs الأخرى أيضًا ولكن MySQL هو الأسهل في الإعداد).
بقدر ما أستطيع أن أحكم عليه ، فإن plyr هي حزمة رائعة أيضًا. ولكن من الطريقة التي تسأل بها ومقارنة مشكلتك في التجميع ، أعتقد أنك تعرف شيئًا عن SQL ، لذلك قد يكون استخدام هذا أسهل بالنسبة لك. هناك وظائف مريحة مثل dbreadtable ، بالإضافة إلى أن بياناتك تزداد حجمًا أكبر ، يمكنك تحديد أجزاء فرعية فقط من بياناتك لتشغيل التحليل الخاص بك فقط بما تحتاجه حقًا.