交换行和数据框中的排序

时间:2016-06-19 00:52:31

标签: r sorting

我发现在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中分享如何做到这一点,我将不胜感激。

2 个答案:

答案 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排序,这是一个有用的选项,IDTIME使用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