هل إعادة تشكيل البيانات هذه ممكنة؟
سؤال
لدي بنية بيانات تبدو كما يلي:
groupA1 groupA2 groupB1 groupB2 date text
0 1 1 1 2013-01-01 the dog
لكل groupB
متغير، أريد إدراج صف واحد لكل عمود له قيمة 1.أحتاج إلى سرد كافة مجموعات من groupA
و groupB
حيث توجد الأرقام 1 في صف واحد، ولكن بعد ذلك قم أيضًا بإضافة التاريخ والنص إلى كل من هذه المجموعات كأعمدة في هذا الصف.
ستظهر البيانات المحولة على النحو التالي:
var_groupB var_groupA date text
groupB1 groupA2 2013-01-01 the dog
groupB2 groupA2 2013-01-01 the dog
لقد حاولت مجموعات من melt
و ddply
لكني أترك دائمًا بدون أحد المتغيرات التي أحتاجها.
شيء واحد حاولته هو melt(x, id.vars=c("text", "date"))
ولكن بعد ذلك أفقد كافة المعلومات حول العلاقات بين groupA
و groupB
.
يمكنني إنجاز ذلك باستخدام حلقة فوضوية، لكنني لم أكن متأكدًا مما إذا كان أ reshape
توجد أداة لست على علم بها ويمكنني القيام بهذه المهمة.
المحلول
يمكنك melt
مرتين، مرة واحدة لكل مجموعة:
y <- melt(x, measure.vars=c("groupA1", "groupA2"),
variable.name="var_groupA", value.name="val_groupA")
y <- melt(y, measure.vars=c("groupB1", "groupB2"),
variable.name="var_groupB", value.name="val_groupB")
سيعطيك ذلك صفًا واحدًا لكل مجموعة من A وB:
date text var_groupA val_groupA var_groupB val_groupB
1 2013-01-01 the dog groupA1 0 groupB1 1
2 2013-01-01 the dog groupA2 1 groupB1 1
3 2013-01-01 the dog groupA1 0 groupB2 1
4 2013-01-01 the dog groupA2 1 groupB2 1
ثم يمكنك تعيين هذا فرعيًا وإزالة أعمدة القيمة:
y <- y[y$val_groupA == 1 & y$val_groupB==1, ]
y <- y[, c("var_groupA", "var_groupB", "date", "text")]
والذي يمنحك ما تريد:
var_groupA var_groupB date text
2 groupA2 groupB1 2013-01-01 the dog
4 groupA2 groupB2 2013-01-01 the dog
بالطبع، إذا كانت مجموعة البيانات الخاصة بك أكثر تعقيدًا مما هي عليه في المثال الخاص بك، فيمكنك جعل هذا الحل أكثر أناقة عن طريق إجراء الصهر والتشكيل الفرعي بطريقة أكثر آلية - على سبيل المثال، اكتشاف أعمدة المجموعة وملء البيانات measure.vars
, variable.name
, ، و value.name
تلقائيا، وربما لأي عدد من المجموعات.
نصائح أخرى
تستبدل أول عبارتين كل 0 في الأعمدة الأربعة الأولى بـ "" وكل 1 باسم العمود الذي يظهر dd2
.العبارتان التاليتان تنشئان كافة مجموعات من groupA
و groupB
لكل صف باستخدام expand.grid
مع أن النتيجة dd3
.أخيراً subset
أن لتلك الصفوف مع لا ""
الإدخالات:
newvals <- function(nm) ifelse(dd[[nm]] == 0, "", nm)
dd2 <- replace(dd, 1:4, lapply(names(dd)[1:4], newvals))
combo <- function(x) data.frame(expand.grid(groupA=c(x[1:2]), groupB=c(x[3:4])),
x$date, x$text)
dd3 <- do.call("rbind", by(dd2, 1:nrow(dd2), combo))
subset(dd3, groupA != "" & groupB != "")
هذا يعطي:
groupA groupB x.date x.text
1.2 groupA2 groupB1 2013-01-01 the dog
1.4 groupA2 groupB2 2013-01-01 the dog