我的数据集大约有300万行,结构如下:
PatientID| Year | PrimaryConditionGroup
---------------------------------------
1 | Y1 | TRAUMA
1 | Y1 | PREGNANCY
2 | Y2 | SEIZURE
3 | Y1 | TRAUMA
作为R的新手,我在找到将数据重塑为下面结构的正确方法时遇到了一些麻烦:
PatientID| Year | TRAUMA | PREGNANCY | SEIZURE
----------------------------------------------
1 | Y1 | 1 | 1 | 0
2 | Y2 | 0 | 0 | 1
3 | Y1 | 1 | 0 | 1
我的问题是:创建data.frame的最快/最优雅的方法是什么,其中PrimaryConditionGroup的值成为列,按PatientID和Year(计算出现次数)分组?
答案 0 :(得分:12)
可能有更简洁的方法可以做到这一点,但是对于纯粹的速度,很难超越基于data.table
的解决方案:
df <- read.table(text="PatientID Year PrimaryConditionGroup
1 Y1 TRAUMA
1 Y1 PREGNANCY
2 Y2 SEIZURE
3 Y1 TRAUMA", header=T)
library(data.table)
dt <- data.table(df, key=c("PatientID", "Year"))
dt[ , list(TRAUMA = sum(PrimaryConditionGroup=="TRAUMA"),
PREGNANCY = sum(PrimaryConditionGroup=="PREGNANCY"),
SEIZURE = sum(PrimaryConditionGroup=="SEIZURE")),
by = list(PatientID, Year)]
# PatientID Year TRAUMA PREGNANCY SEIZURE
# [1,] 1 Y1 1 1 0
# [2,] 2 Y2 0 0 1
# [3,] 3 Y1 1 0 0
编辑: aggregate()
提供“基本R”解决方案,可能会或可能不会更具惯用性。 (唯一的复杂因素是聚合返回一个矩阵,而不是data.frame;下面的第二行修复了这个。)
out <- aggregate(PrimaryConditionGroup ~ PatientID + Year, data=df, FUN=table)
out <- cbind(out[1:2], data.frame(out[3][[1]]))
第二次编辑最后,使用reshape
包的简洁解决方案可以让您到达同一个地方。
library(reshape)
mdf <- melt(df, id=c("PatientID", "Year"))
cast(PatientID + Year ~ value, data=j, fun.aggregate=length)
答案 1 :(得分:1)
在版本melt
中,C中实现了快速dcast
和>=1.9.0
data.table特定方法。这里与@Josh的帖子中关于300万行数据的其他优秀答案进行了比较(仅排除基数:::汇总,因为它花了很长时间)。
有关NEWS条目的更多信息,请转到here。
我假设您有1000名患者,总共5年。您可以相应地调整变量patients
和year
。
require(data.table) ## >= 1.9.0
require(reshape2)
set.seed(1L)
patients = 1000L
year = 5L
n = 3e6L
condn = c("TRAUMA", "PREGNANCY", "SEIZURE")
# dummy data
DT <- data.table(PatientID = sample(patients, n, TRUE),
Year = sample(year, n, TRUE),
PrimaryConditionGroup = sample(condn, n, TRUE))
DT_dcast <- function(DT) {
dcast.data.table(DT, PatientID ~ Year, fun.aggregate=length)
}
reshape2_dcast <- function(DT) {
reshape2:::dcast(DT, PatientID ~ Year, fun.aggregate=length)
}
DT_raw <- function(DT) {
DT[ , list(TRAUMA = sum(PrimaryConditionGroup=="TRAUMA"),
PREGNANCY = sum(PrimaryConditionGroup=="PREGNANCY"),
SEIZURE = sum(PrimaryConditionGroup=="SEIZURE")),
by = list(PatientID, Year)]
}
# system.time(.) timed 3 times
# Method Time_rep1 Time_rep2 Time_rep3
# dcast_DT 0.393 0.399 0.396
# reshape2_DT 3.784 3.457 3.605
# DT_raw 0.647 0.680 0.657
dcast.data.table
比使用data.table
的正常聚合快约1.6倍,比reshape2:::dcast
快8.8倍。