我发现在R中的数据框中对某些行进行排序有点棘手。数据具有以下结构。
df <-
ID TIME DVID AMT DV PERIOD
1 0 0 50 NA 1
1 0.5 1 0 10 1
1 0.5 2 0 15 1
2 600 0 100 NA 2
2 600 1 0 2.5 2
2 600 2 0 4 2
2 602 1 0 20 2
2 602 2 0 35 2
3 800 0 50 NA 3
3 800 1 0 5 3
3 800 2 0 10 3
对于PERIOD >= 2
我想将DVID的行交换为DVID 1,2,然后是0,如dfout
下面的输出数据框所示。数据必须按ID,TIME,PERIOD排序。
我尝试使用orderBy
,但可以达到我的目标。使用orderBy
的一个例子就是这个。
library(doBy)
dfout <- orderBy(~ID+TIME+PERIOD, data=df)
输出应为:
dfout <-
ID TIME DVID AMT DV PERIOD
1 0 0 50 NA 1
1 0.5 1 0 10 1
1 0.5 2 0 15 1
2 600 1 0 2.5 2
2 600 2 0 4 2
2 600 0 100 NA 2
2 602 1 0 20 2
2 602 2 0 35 2
3 800 1 0 5 3
3 800 2 0 10 3
3 800 0 50 NA 3
如果有人在R中分享如何做到这一点,我将不胜感激。
答案 0 :(得分:4)
我们可以在没有任何小组的情况下这样做,并且通过这样做它应该更快。
library(dplyr)
df %>%
arrange(ID, PERIOD, TIME, replace(DVID, PERIOD > 1 & DVID==0, 3))
# ID TIME DVID AMT DV PERIOD
#1 1 0.0 0 50 NA 1
#2 1 0.5 1 0 10.0 1
#3 1 0.5 2 0 15.0 1
#4 2 600.0 1 0 2.5 2
#5 2 600.0 2 0 4.0 2
#6 2 600.0 0 100 NA 2
#7 2 602.0 1 0 20.0 2
#8 2 602.0 2 0 35.0 2
#9 3 800.0 1 0 5.0 3
#10 3 800.0 2 0 10.0 3
#11 3 800.0 0 50 NA 3
或使用data.table
library(data.table)
setDT(df)[PERIOD > 1 & DVID==0, DVID1:= 3][order(ID, TIME, PERIOD,
pmax(DVID, DVID1, na.rm=TRUE))][, DVID1 := NULL][]
或使用base R
df[order(df$ID, df$PERIOD, df$TIME, with(df, replace(DVID,PERIOD>1 & DVID ==0, 3))),]
# ID TIME DVID AMT DV PERIOD
#1 1 0.0 0 50 NA 1
#2 1 0.5 1 0 10.0 1
#3 1 0.5 2 0 15.0 1
#5 2 600.0 1 0 2.5 2
#6 2 600.0 2 0 4.0 2
#4 2 600.0 0 100 NA 2
#7 2 602.0 1 0 20.0 2
#8 2 602.0 2 0 35.0 2
#10 3 800.0 1 0 5.0 3
#11 3 800.0 2 0 10.0 3
#9 3 800.0 0 50 NA 3
答案 1 :(得分:3)
通过在0
大于1时将3
指定为Period
然后由DVID
组按PERIOD
排序,这是一个有用的选项,ID
和TIME
使用data.table
包:
library(data.table)
setDT(df)
df[,.SD[order(ifelse(PERIOD > 1 & DVID == 0, 3, DVID))], .(PERIOD, ID, TIME)]
# PERIOD ID TIME DVID AMT DV
# 1: 1 1 0.0 0 50 NA
# 2: 1 1 0.5 1 0 10.0
# 3: 1 1 0.5 2 0 15.0
# 4: 2 2 600.0 1 0 2.5
# 5: 2 2 600.0 2 0 4.0
# 6: 2 2 600.0 0 100 NA
# 7: 2 2 602.0 1 0 20.0
# 8: 2 2 602.0 2 0 35.0
# 9: 3 3 800.0 1 0 5.0
#10: 3 3 800.0 2 0 10.0
#11: 3 3 800.0 0 50 NA
避免ifelse
语句的另一种方法:
df[,.SD[order(((PERIOD > 1)*2 + DVID)%%3)], .(PERIOD, ID, TIME)]
# PERIOD ID TIME DVID AMT DV
# 1: 1 1 0.0 0 50 NA
# 2: 1 1 0.5 1 0 10.0
# 3: 1 1 0.5 2 0 15.0
# 4: 2 2 600.0 1 0 2.5
# 5: 2 2 600.0 2 0 4.0
# 6: 2 2 600.0 0 100 NA
# 7: 2 2 602.0 1 0 20.0
# 8: 2 2 602.0 2 0 35.0
# 9: 3 3 800.0 1 0 5.0
# 10: 3 3 800.0 2 0 10.0
# 11: 3 3 800.0 0 50 NA