R 对每个唯一ID的前4个观察值进行分组
我有一个由4列和几千行组成的数据框架。我根据他们的ID(降序)的第四列对数据帧进行排序,然后是第二列(升序)。以下是我的数据:R 对每个唯一ID的前4个观察值进行分组,r,dataframe,subset,R,Dataframe,Subset,我有一个由4列和几千行组成的数据框架。我根据他们的ID(降序)的第四列对数据帧进行排序,然后是第二列(升序)。以下是我的数据: X1 X2 X3 X4 24 1 23 25 21 3 19 25 19 6 20 25 11 12 14 25 14 9 21 24 3 12 25 24 24 15 23 24 8 1 4 23 17 4 12 23 16 11 23 23 20 19 21 23 24 19 16 23 19 20 7 23 19
X1 X2 X3 X4
24 1 23 25
21 3 19 25
19 6 20 25
11 12 14 25
14 9 21 24
3 12 25 24
24 15 23 24
8 1 4 23
17 4 12 23
16 11 23 23
20 19 21 23
24 19 16 23
19 20 7 23
19 22 22 22
11 2 18 21
15 9 19 21
10 14 9 21
17 15 19 21
16 20 6 21
我试图保持每个ID的最高4个值(如果可用),我希望的输出是
X1 X2 X3 X4
24 1 23 25
21 3 19 25
19 6 20 25
11 12 14 25
14 9 21 24
3 12 25 24
24 15 23 24
8 1 4 23
17 4 12 23
16 11 23 23
20 19 21 23
19 22 22 22
11 2 18 21
15 9 19 21
10 14 9 21
17 15 19 21
# note that 2 of the 23 ID observations and one of the 21 ID observations were removed.
我想知道是否有一些短命令可以为我做这项工作?我能想到一个大约1页长的命令!这是根据第4列对数据进行子集,取前5列,然后再重新定位。但这听起来太不专业了
下面是生成类似示例的命令:
m0 <- matrix(0, 100, 4)
df <- data.frame(apply(m0, c(1,2), function(x) sample(c(0:25),1)))
##fix(df)
odf <- df[order(-as.numeric(df$X4), as.numeric(df$X2)), ]
m0可能数据。表
:
require(data.table)
df<-read.table(header=T,text=" X1 X2 X3 X4
24 1 23 25
21 3 19 25
19 6 20 25
11 12 14 25
14 9 21 24
3 12 25 24
24 15 23 24
8 1 4 23
17 4 12 23
16 11 23 23
20 19 21 23
24 19 16 23
19 20 7 23
19 22 22 22
11 2 18 21
15 9 19 21
10 14 9 21
17 15 19 21
16 20 6 21")
data.table(df)[,.SD[order(X2)][1:4,],by="X4"][!is.na(X3)][,list(X1,X2,X3,X4)]
X1 X2 X3 X4
1: 24 1 23 25
2: 21 3 19 25
3: 19 6 20 25
4: 11 12 14 25
5: 14 9 21 24
6: 3 12 25 24
7: 24 15 23 24
8: 8 1 4 23
9: 17 4 12 23
10: 16 11 23 23
11: 20 19 21 23
12: 19 22 22 22
13: 11 2 18 21
14: 15 9 19 21
15: 10 14 9 21
16: 17 15 19 2
可能是数据。表:
require(data.table)
df<-read.table(header=T,text=" X1 X2 X3 X4
24 1 23 25
21 3 19 25
19 6 20 25
11 12 14 25
14 9 21 24
3 12 25 24
24 15 23 24
8 1 4 23
17 4 12 23
16 11 23 23
20 19 21 23
24 19 16 23
19 20 7 23
19 22 22 22
11 2 18 21
15 9 19 21
10 14 9 21
17 15 19 21
16 20 6 21")
data.table(df)[,.SD[order(X2)][1:4,],by="X4"][!is.na(X3)][,list(X1,X2,X3,X4)]
X1 X2 X3 X4
1: 24 1 23 25
2: 21 3 19 25
3: 19 6 20 25
4: 11 12 14 25
5: 14 9 21 24
6: 3 12 25 24
7: 24 15 23 24
8: 8 1 4 23
9: 17 4 12 23
10: 16 11 23 23
11: 20 19 21 23
12: 19 22 22 22
13: 11 2 18 21
14: 15 9 19 21
15: 10 14 9 21
16: 17 15 19 2
我用一个set.seed
调用再次包含您的代码,这样它就完全可以复制了
set.seed(1)
m0 <- matrix(0, 100, 4)
df <- data.frame(apply(m0, c(1,2), function(x) sample(c(0:25),1)))
odf <- df[order(-as.numeric(df$X4), as.numeric(df$X2)), ]
我用一个set.seed
调用再次包含您的代码,这样它就完全可以复制了
set.seed(1)
m0 <- matrix(0, 100, 4)
df <- data.frame(apply(m0, c(1,2), function(x) sample(c(0:25),1)))
odf <- df[order(-as.numeric(df$X4), as.numeric(df$X2)), ]
我认为托马斯的解决方案很好,但可以改进。我猜拆分、重组和重新排序可能会很耗时
相反,我将创建一个向量,从中我们可以得到子集
使用ave
很容易做到这一点,而且应该可以工作,因为数据已经排序
继续自:
odf <- df[order(-as.numeric(df$X4), as.numeric(df$X2)), ]
前两种方法(Thomas和我的第一种方法)需要相当长的时间,因此,我将不进行基准测试,只对它们计时一次
system.time(fun1())
# user system elapsed
# 6.645 0.007 6.670
system.time(fun2())
# user system elapsed
# 4.053 0.004 4.186
下面是“dplyr”和“data.table”结果
比较“dplyr”和“data.table”方法的输出:
out_DT <- fun3()
out_DP <- fun4()
out_DT
# X1 X2 X3 X4
# 1: 340 0 708 1000
# 2: 144 1 667 1000
# 3: 73 2 142 1000
# 4: 79 2 826 1000
# 5: 169 0 870 999
# ---
# 4000: 46 4 2 1
# 4001: 88 0 809 0
# 4002: 535 0 522 0
# 4003: 75 3 234 0
# 4004: 983 3 492 0
head(out_DP, 5)
# Source: local data frame [5 x 5]
# Groups: X4
#
# X1 X2 X3 X4 vals
# 1 340 0 708 1000 1
# 2 144 1 667 1000 2
# 3 73 2 142 1000 3
# 4 79 2 826 1000 4
# 5 169 0 870 999 1
tail(out_DP, 5)
# Source: local data frame [5 x 5]
# Groups: X4
#
# X1 X2 X3 X4 vals
# 4000 46 4 2 1 4
# 4001 88 0 809 0 1
# 4002 535 0 522 0 2
# 4003 75 3 234 0 3
# 4004 983 3 492 0 4
我认为托马斯的解决方案很好,但可以改进。我猜拆分、重组和重新排序可能会很耗时
相反,我将创建一个向量,从中我们可以得到子集
使用ave
很容易做到这一点,而且应该可以工作,因为数据已经排序
继续自:
odf <- df[order(-as.numeric(df$X4), as.numeric(df$X2)), ]
前两种方法(Thomas和我的第一种方法)需要相当长的时间,因此,我将不进行基准测试,只对它们计时一次
system.time(fun1())
# user system elapsed
# 6.645 0.007 6.670
system.time(fun2())
# user system elapsed
# 4.053 0.004 4.186
下面是“dplyr”和“data.table”结果
比较“dplyr”和“data.table”方法的输出:
out_DT <- fun3()
out_DP <- fun4()
out_DT
# X1 X2 X3 X4
# 1: 340 0 708 1000
# 2: 144 1 667 1000
# 3: 73 2 142 1000
# 4: 79 2 826 1000
# 5: 169 0 870 999
# ---
# 4000: 46 4 2 1
# 4001: 88 0 809 0
# 4002: 535 0 522 0
# 4003: 75 3 234 0
# 4004: 983 3 492 0
head(out_DP, 5)
# Source: local data frame [5 x 5]
# Groups: X4
#
# X1 X2 X3 X4 vals
# 1 340 0 708 1000 1
# 2 144 1 667 1000 2
# 3 73 2 142 1000 3
# 4 79 2 826 1000 4
# 5 169 0 870 999 1
tail(out_DP, 5)
# Source: local data frame [5 x 5]
# Groups: X4
#
# X1 X2 X3 X4 vals
# 4000 46 4 2 1 4
# 4001 88 0 809 0 1
# 4002 535 0 522 0 2
# 4003 75 3 234 0 3
# 4004 983 3 492 0 4
out\u DT感谢Thomas,所以这基本上是相同的想法,但更好的脚本:)很受欢迎。只是将其转换为“dplyr”方法。没有太多使用dplyr,所以甚至不确定它是否是最好的方法,但我提出的解决方案是快速的。感谢@AnandaMahto,我可能需要最快的方法来解决这个问题,数据集是巨大的!我将阅读您在答复中发布的详细信息。Cheers Hanks Thomas,所以这基本上是相同的想法,但更好的脚本:)很受欢迎。只是将其转换为“dplyr”方法。没有太多使用dplyr,所以甚至不确定它是否是最好的方法,但我提出的解决方案是快速的。感谢@AnandaMahto,我可能需要最快的方法来解决这个问题,数据集是巨大的!我将阅读您在答复中发布的详细信息。干杯+1。或者更好的方法是,将第一个顺序也放入data.table
中:data.table(df)[order(-X4)][,.SD[order(X2)][1:4,],by=“X4”][!is.na(X3)],list(X1,X2,X3,X4)]
+1。或者更好的方法是,将第一个顺序也放入data.table
中:data.table(df)[order(-X4)][,.SD[order(X2)][1:4,],by=“X4”][!is.na(X3)],list(X1,X2,X3,X4)]
+1我怀疑在我的版本和你的第一个版本中,重新排序是非常耗时的部分。我们是否在order
上的任何其他地方运行过基准测试呢?@Thomas,order
肯定是一个瓶颈,当我们有很多值要订购时,这一点就变得越来越严重了。+1我怀疑在我的版本和你的第一个版本中,重新排序是非常耗时的部分。我们是否在order
上的任何其他地方运行过基准测试呢?@Thomas,order
无疑是一个瓶颈,当我们有很多值要订购时,它变得越来越重要。
system.time(fun1())
# user system elapsed
# 6.645 0.007 6.670
system.time(fun2())
# user system elapsed
# 4.053 0.004 4.186
microbenchmark(fun3(), fun4(), times = 20)
# Unit: seconds
# expr min lq median uq max neval
# fun3() 2.157956 2.221746 2.303286 2.343951 2.392391 20
# fun4() 1.169212 1.180780 1.194994 1.206651 1.369922 20
out_DT <- fun3()
out_DP <- fun4()
out_DT
# X1 X2 X3 X4
# 1: 340 0 708 1000
# 2: 144 1 667 1000
# 3: 73 2 142 1000
# 4: 79 2 826 1000
# 5: 169 0 870 999
# ---
# 4000: 46 4 2 1
# 4001: 88 0 809 0
# 4002: 535 0 522 0
# 4003: 75 3 234 0
# 4004: 983 3 492 0
head(out_DP, 5)
# Source: local data frame [5 x 5]
# Groups: X4
#
# X1 X2 X3 X4 vals
# 1 340 0 708 1000 1
# 2 144 1 667 1000 2
# 3 73 2 142 1000 3
# 4 79 2 826 1000 4
# 5 169 0 870 999 1
tail(out_DP, 5)
# Source: local data frame [5 x 5]
# Groups: X4
#
# X1 X2 X3 X4 vals
# 4000 46 4 2 1 4
# 4001 88 0 809 0 1
# 4002 535 0 522 0 2
# 4003 75 3 234 0 3
# 4004 983 3 492 0 4