gpt4 book ai didi

R:没有for循环的子集和排序大数据帧

转载 作者:行者123 更新时间:2023-12-01 09:22:56 24 4
gpt4 key购买 nike

我有 97M 行的长表。每行包含一个人所采取的行动的信息和该行动的时间戳,格式为:

actions <- c("walk","sleep", "run","eat")
people <- c("John","Paul","Ringo","George")
timespan <- seq(1000,2000,1)

set.seed(28100)
df.in <- data.frame(who = sample(people, 10, replace=TRUE),
what = sample(actions, 10, replace=TRUE),
when = sample(timespan, 10, replace=TRUE))

df.in
# who what when
# 1 Paul eat 1834
# 2 Paul sleep 1295
# 3 Paul eat 1312
# 4 Ringo eat 1635
# 5 John sleep 1424
# 6 George run 1092
# 7 Paul walk 1849
# 8 John run 1854
# 9 George sleep 1036
# 10 Ringo walk 1823

每个 Action 都可以由一个人执行或不执行,并且可以按任何顺序执行 Action 。

我有兴趣总结我的数据集中的操作顺序。特别是对于每个人,我想找出首先、第二、第三和第四次采取的行动。 如果一个 Action 被多次执行,我只对第一次发生感兴趣。然后,如果有人运行、吃饭、吃饭、运行和 sleep ,我有兴趣总结一下,例如 runeatsleep

df.out <- data.frame(who = factor(character(), levels=people),
action1 = factor(character(), levels=actions),
action2 = factor(character(), levels=actions),
action3 = factor(character(), levels=actions),
action4 = factor(character(), levels=actions))

我可以通过 forloop 获得我想要的:

for (person in people) {
tmp <- subset(df.in, who==person)
tmp <- tmp[order(tmp$when),]
chrono_list <- unique(tmp$what)
df.out <- rbind(df.out, data.frame(who = person,
action1 = chrono_list[1],
action2 = chrono_list[2],
action3 = chrono_list[3],
action4 = chrono_list[4]))
}

df.out
# who action1 action2 action3 action4
# 1 John sleep run <NA> <NA>
# 2 Paul sleep eat walk <NA>
# 3 Ringo eat walk <NA> <NA>
# 4 George sleep run <NA> <NA>

在没有循环的情况下也能以更有效的方式获得这个结果吗?

最佳答案

我们可以使用 data.table 的开发版本中的 dcast,即。 v1.9.5。我们可以从 here 安装它

library(data.table)#v1.9.5+
dcast(setDT(df.in)[order(when),action:= paste0('action', 1:.N) ,who],
who~action, value.var='what')

如果您需要 unique 每个“谁”的“什么”

dcast(setDT(df.in)[, .SD[!duplicated(what)], who][order(when),
action:= paste0('action', 1:.N), who], who~action, value.var='what')
# who action1 action2 action3
#1: George sleep run NA
#2: John sleep run NA
#3: Paul sleep eat walk
#4: Ringo eat walk NA

或者使用 .I 会快一点

 ind <- setDT(df.in)[,.I[!duplicated(what)], who]$V1 

dcast(df.in[ind][order(when),action:= paste0('action', 1:.N) ,who],
who~action, value.var='what')

或者使用 setorderunique 这可能是一种内存效率,因为 setorder 通过引用重新排序数据集。

 dcast(unique(setorder(setDT(df.in), who, when), by=c('who', 'what'))[,
action:= paste0('action', 1:.N), who], who~action, value.var='what')
# who action1 action2 action3
#1: George sleep run NA
#2: John sleep run NA
#3: Paul sleep eat walk
#4: Ringo eat walk NA

关于R:没有for循环的子集和排序大数据帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30220123/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com