Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 对每个唯一ID的前4个观察值进行分组_R_Dataframe_Subset - Fatal编程技术网

R 对每个唯一ID的前4个观察值进行分组

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

我有一个由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 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