我对R来说比较新,并且在R中“渲染”我的所有代码都很困难。尽管我很欣赏这是正确的方法。
我需要在数据框中设置一个值作为ID的最短时间。
ID isTrue RealTime MinTime
1 TRUE 16
1 FALSE 8
1 TRUE 10
2 TRUE 7
2 TRUE 30
3 FALSE 3
要变成:
ID isTrue RealTime MinTime
1 TRUE 16 10
1 FALSE 8
1 TRUE 10 10
2 TRUE 7 7
2 TRUE 30 7
3 FALSE 3
以下作品完美无缺。但是,运行需要10分钟,这并不理想:
for (i in 1:nrow(df)){
if (df[i,'isTrue']) {
prevTime <- sqldf(paste('Select min(MinTime) from dfStageIV where ID =',df[i,'ID'],sep=" "))[1,1]
if (is.na(prevTime) | is.na(df[i,'MinTime']) | df[i,'MinTime'] < prevTime){
df[i,'MinTime']<-dfStageIV[i,'RealTime']
} else {
dfStageIV[i,'MinTime']<-prevTime
}
}
}
我该如何正确地做到这一点?我认为使用for或do循环不是R中的最佳方法。我一直在查看apply()和aggregate.data.frame()函数,但无法理解如何执行此操作。有人能指出我正确的方向吗?非常感谢!!
答案 0 :(得分:2)
以下是使用ave
,pmax
和is.na
的双行基础R解决方案。
# calculate minimum for each ID, excluding FALSE instances
df$MinTime <- ave(pmax(df$RealTime, (!df$isTrue) * max(df$RealTime)), df$ID, FUN=min)
# turn FALSE instances into NA
is.na(df$MinTime) <- (!df$isTrue)
返回
df
ID isTrue RealTime MinTime
1 1 TRUE 16 10
2 1 FALSE 8 NA
3 1 TRUE 10 10
4 2 TRUE 7 7
5 2 TRUE 30 7
6 3 FALSE 3 NA
在第一行中,pmax
用于构造观察的向量,如果df$isTrue
为TRUE或data.frame中的最大实时值。这个新向量用于最小计算。 FALSE值在第二行中设置为NA。
数据强>
df <- read.table(header=T, text="ID isTrue RealTime
1 TRUE 16
1 FALSE 8
1 TRUE 10
2 TRUE 7
2 TRUE 30
3 FALSE 3")
答案 1 :(得分:0)
dplyr
链的速度应该快得多。在这里,我们按ID和组对数据框进行分组,并在组级别获取最小值。然后我们可以再次取消组合,只需删除F
最小值。
library(dplyr)
df %>%
group_by(ID, isTrue) %>%
mutate(Min.all = min(RealTime)) %>%
ungroup() %>%
transmute(ID, isTrue, RealTime, MinTime = ifelse(isTrue == T, Min.all, ""))
输出:
# A tibble: 6 × 4
ID isTrue RealTime MinTime
<int> <lgl> <int> <chr>
1 1 TRUE 16 10
2 1 FALSE 8
3 1 TRUE 10 10
4 2 TRUE 7 7
5 2 TRUE 30 7
6 3 FALSE 3
如果你要进行大量的数据帧操作,我真的建议你熟悉dplyr
。
答案 2 :(得分:0)
有人建议使用ave()函数和以下工作并且速度很快,尽管它会返回大量警告:
df$MinTime<-ave(df$RealTime,df$ID, df$isTrue, FUN = min)
df$MinTime<-ifelse(df$isTrue, df$MinTime,NA).
答案 3 :(得分:0)
问题中的代码可以通过SQL中的全部内容或R中的所有内容(适当的矢量化)而不是一半来简化。已经有一些R解决方案,所以这里有一个SQL解决方案,表明问题相当于聚合自定义自联接。
library(sqldf)
sqldf("select a.*, min(b.RealTime) minRealTime
from df a
left join df b on a.ID = b.ID and a.isTRUE and b.isTRUE
group by a.rowid")
,并提供:
ID isTrue RealTime minRealTime
1 1 TRUE 16 10
2 1 FALSE 8 NA
3 1 TRUE 10 10
4 2 TRUE 7 7
5 2 TRUE 30 7
6 3 FALSE 3 NA