ak3*_*t0n 3 performance r data-mining dataframe
我是R的新手,无法弄清楚我在下面的代码中可能做错了什么以及如何加快速度.我有一个数据集,并希望添加一个包含从两列数据计算的平均值的列.请看下面的代码(警告:可能需要一些时间来阅读我的问题,但代码在R中正常运行):
首先让我定义一个数据集df(我再次为代码的长描述道歉)
> df<-data.frame(prediction=sample(c(0,1),10,TRUE),subject=sample(c("car","dog","man","tree","book"),10,TRUE))
> df
prediction subject
1 0 man
2 1 dog
3 0 man
4 1 tree
5 1 car
6 1 tree
7 1 dog
8 0 tree
9 1 tree
10 1 tree
Run Code Online (Sandbox Code Playgroud)
接下来,我将一个名为subjectRate的新列添加到df中
df$subjectRate <- with(df,ave(prediction,subject))
> df
prediction subject subjectRate
1 0 man 0.0
2 1 dog 1.0
3 0 man 0.0
4 1 tree 0.8
5 1 car 1.0
6 1 tree 0.8
7 1 dog 1.0
8 0 tree 0.8
9 1 tree 0.8
10 1 tree 0.8
Run Code Online (Sandbox Code Playgroud)
从新表定义中我生成一个rateMap,以便使用之前获得的平均值初始化的subjectRate列自动填充新数据.
rateMap <- df[!duplicated(df[, c("subjectRate")]), c("subject","subjectRate")]
> rateMap
subject subjectRate
1 man 0.0
2 dog 1.0
4 tree 0.8
Run Code Online (Sandbox Code Playgroud)
现在,我正在定义一个新数据集,其中包含df和新主题中的旧主题
> dfNew<-data.frame(prediction=sample(c(0,1),15,TRUE),subject=sample(c("car","dog","man","cat","book","computer"),15,TRUE))
> dfNew
prediction subject
1 1 man
2 0 cat
3 1 computer
4 0 dog
5 0 book
6 1 cat
7 1 car
8 0 book
9 0 computer
10 1 dog
11 0 cat
12 0 book
13 1 dog
14 1 man
15 1 dog
Run Code Online (Sandbox Code Playgroud)
我的问题:如何有效地创建第三列?目前我正在运行下面的测试,我在地图中查找主题率,如果找到则输入值,否则输入0.5.
> all_facts<-levels(factor(rateMap$subject))
> dfNew$subjectRate <- sapply(dfNew$subject,function(t) ifelse(t %in% all_facts,rateMap[as.character(rateMap$subject) == as.character(t),][1,"subjectRate"],0.5))
> dfNew
prediction subject subjectRate
1 1 man 0.0
2 0 cat 0.5
3 1 computer 0.5
4 0 dog 1.0
5 0 book 0.5
6 1 cat 0.5
7 1 car 0.5
8 0 book 0.5
9 0 computer 0.5
10 1 dog 1.0
11 0 cat 0.5
12 0 book 0.5
13 1 dog 1.0
14 1 man 0.0
15 1 dog 1.0
Run Code Online (Sandbox Code Playgroud)
但与真正的数据集(20多万行)用类似多列受到计算平均,代码需要很长的时间来运行.有人可能会建议一个更好的方法去做我想要实现的目标吗?也许是一些合并或其他什么,但我没有想法.谢谢.
我怀疑(但我不确定,因为我还没有测试过)这会更快:
dfNew$subjectRate <- rateMap$subjectRate[match(dfNew$subject,rateMap$subject)]
Run Code Online (Sandbox Code Playgroud)
因为它主要使用索引和match.我想,这当然有点简单.这将用NAs而不是0.5来填充"新"值,然后可以根据需要填写,
dfNew$subjectRate[is.na(dfNew$subjectRate)] <- newValue
Run Code Online (Sandbox Code Playgroud)
如果这篇ave文章特别慢,那么现在的标准建议是使用data.table包:
require(data.table)
dft <- as.data.table(df)
setkeyv(dft, "subject")
dft[, subjectRate := mean(prediction), by = subject]
Run Code Online (Sandbox Code Playgroud)
这可能会吸引一些评论,建议在最后一行中提高数据表聚合的速度.实际上,使用pure data.tables进行合并或连接可能更加流畅(而且速度快),因此您可能也想调查该选项.(请参阅最底层?data.table的一些示例.)
| 归档时间: |
|
| 查看次数: |
621 次 |
| 最近记录: |