我对R比较陌生,每次我需要重塑"数据,我绝对感到困惑。我的数据看起来像这样:
HAVE:
ID ever_smoked alcoholic medication dosage
1 1 no no humira/adalimumab 40mg
2 1 no no prednisone 15mg
3 1 no no azathioprine 30mg
4 1 no no rowasa 9mg
5 2 yes no lialda 20mg
6 2 yes no mercaptopurine 1g
7 2 yes no asacol 1600mg
WANT:
ID ever_smoked alcoholic medication
1 1 no no humira/adalimumab, prednisone, azathioprine, rowasa
2 2 yes no lialda, mercaptopurine, asacol
dosage most_recent_med most_recent_dose
1 40mg, 15mg, 30mg, 9mg rowasa 9mg
2 20mg, 1g, 1600mg asacol 1600mg
(请注意,它应该是2个观察值和7个变量)。
本质上,我想(1)只折叠一些变量,(2)保留其他变量的第一行,并且(3)根据某些变量的最后一个条目创建2个新变量变量。
重现的代码:
have <- data.frame(ID = c(1, 1, 1, 1, 2, 2, 2),
ever_smoked = c("no", "no", "no", "no", "yes", "yes", "yes"),
alcoholic = c("no", "no", "no", "no", "no", "no", "no"),
medication = c("humira/adalimumab", "prednisone", "azathioprine", "rowasa", "lialda", "mercaptopurine", "asacol"),
dosage = c("40mg", "15mg", "30mg", "9mg", "20mg", "1g", "1600mg"), stringsAsFactors = FALSE)
want <- data.frame(ID = c(1, 2),
ever_smoked = c("no", "yes"),
alcoholic = c("no", "no"),
medication = c("humira/adalimumab, prednisone, azathioprine, rowasa", "lialda, mercaptopurine, asacol"),
dosage = c("40mg, 15mg, 30mg, 9mg", "20mg, 1g, 1600mg"),
most_recent_med = c("rowasa", "asacol"),
most_recent_dose = c("9mg", "1600mg"), stringsAsFactors = FALSE)
感谢。
答案 0 :(得分:4)
以下是一些不同的方法:
1)sqldf
library(sqldf)
sqldf("select ID,
ever_smoked,
alcoholic,
group_concat(medication) as medication,
group_concat(dosage) as dosage,
medication as last_medication,
dosage as last_doage
from have
group by ID")
,并提供:
ID ever_smoked alcoholic medication dosage last_medication last_doage
1 1 no no humira/adalimumab,prednisone,azathioprine,rowasa 40mg,15mg,30mg,9mg rowasa 9mg
2 2 yes no lialda,mercaptopurine,asacol 20mg,1g,1600mg asacol 1600mg
2)data.table
library(data.table)
have_dt <- data.table(have)
have_dt[, list(medication = toString(medication),
dosage = toString(dosage),
last_medication = medication[.N],
last_dosage = dosage[.N]),
by = "ID,ever_smoked,alcoholic"]
,并提供:
ID ever_smoked alcoholic medication dosage last_medication last_dosage
1: 1 no no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg rowasa 9mg
2: 2 yes no lialda, mercaptopurine, asacol 20mg, 1g, 1600mg asacol 1600mg
3)base - by
do.call("rbind", by(have, have$ID, with, data.frame(
ID = ID[1],
ever_smoked = ever_smoked[1],
alcoholic = alcoholic[1],
medication = toString(medication),
dosage = toString(dosage),
last_medication = tail(medication, 1),
last_dosage = tail(dosage, 1))))
,并提供:
ID ever_smoked alcoholic medication dosage last_medication last_dosage
1 1 no no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg rowasa 9mg
2 2 yes no lialda, mercaptopurine, asacol 20mg, 1g, 1600mg asacol 1600mg
请注意,这可以写成:
do.call("rbind", by(have, have$ID, function(x) with(x, data.frame(
ID = ID[1],
ever_smoked = ever_smoked[1],
alcoholic = alcoholic[1],
medication = toString(medication),
dosage = toString(dosage),
last_medication = tail(medication, 1),
last_dosage = tail(dosage, 1)))))
4)base - aggregate
aggregate(. ~ ID + ever_smoked + alcoholic, have,
function(x) c(values = toString(x), last = as.character(tail(x, 1))))
,并提供:
ID ever_smoked alcoholic medication.values medication.last dosage.values dosage.last
1 1 no no humira/adalimumab, prednisone, azathioprine, rowasa rowasa 40mg, 15mg, 30mg, 9mg 9mg
2 2 yes no lialda, mercaptopurine, asacol asacol 20mg, 1g, 1600mg 1600mg
请注意,这将返回一个2 x 5数据框,其中最后两列是每个2列矩阵,这比拼合形式更方便索引,但如果首选扁平,则:do.call("data.frame", DF)
答案 1 :(得分:3)
这是一个摘要流程,您可以使用summarise_all
并传递两个函数来汇总每一列:一列用toString
折叠列,一列用last
取最后一行:
have %>%
group_by(ID, ever_smoked, alcoholic) %>%
summarise_all(funs(toString(.), most_recent = last(.)))
# A tibble: 2 x 7
# Groups: ID, ever_smoked [?]
# ID ever_smoked alcoholic medication_toString dosage_toString medication_most_recent dosage_most_recent
# <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
#1 1 no no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg rowasa 9mg
#2 2 yes no lialda, mercaptopurine, asacol 20mg, 1g, 1600mg asacol 1600mg
假设 ever_smoked 和 alcoholic 对于每个ID都是唯一的。