R语言:如何将which和which.max的功能合二为一?

4

我有一个简单的问题,如何同时使用whichwhich.max

我想选择行id == B13639J2的最大epnum。 我需要检索行号,因为我需要对变量进行一些手动更改。

因此,id == 'B13639J2'的行的最大epnum

           id   epnum start
95528 B13639J2     1     0
95529 B13639J2     2   860
95530 B13639J2     3  1110
95531 B13639J2     4  1155
95532 B13639J2     5  1440

我在想要如何简单地完成类似以下的操作:
dta[which(dta$id == 'B13639J2' & which.max(dta$epnum)), ] 

最后,我需要删除被标记的行。
谢谢。
数据。
dta = structure(list(id = c("B13639J1", "B13639J1", "B13639J1", "B13639J1", 
"B13639J1", "B13639J1", "B13639J1", "B13639J1", "B13639J2", "B13639J2", 
"B13639J2", "B13639J2", "B13639J2"), epnum = c(4, 5, 6, 7, 8, 
9, 10, 11, 1, 2, 3, 4, 5), start = c(420, 425, 435, 540, 570, 
1000, 1310, 1325, 0, 860, 1110, 1155, 1440)), .Names = c("id", 
"epnum", "start"), row.names = 95520:95532, class = "data.frame")

1
我认为需要一个两步骤的过程。在之前的例子中,所有ID中都存在相同的“max”值,因此单步条件起作用。在这里,我们必须首先过滤“id”,然后需要第二个过滤器。就像我上次提到的双切片过程一样。我应该用不同的数据集检查条件。我的错! - akrun
3个回答

8
如果我们使用数字索引(which/which.max),一个选项是使用dplyr中的slice。这里需要双重slice。首先,我们子集化'id'即'B13639J2',然后再次对'epnum'值的max进行子集化。
 library(dplyr)
 slice(dta, which(id=='B13639J2')) %>%
                   slice(which.max(epnum))
 #        id epnum start
 #1 B13639J2     5  1440

或者我们按照'id'进行分组,按照'epnum'的降序排列,并筛选出指定'id'的第一行。

  dta1 <- dta %>% 
             group_by(id) %>% 
             arrange(desc(epnum)) %>%
             filter(id=='B13639J2', row_number()==1L)

如果我们想从数据集中删除这一行,一个选项是使用原始数据集进行anti_join
  anti_join(dta, dta1)

通过更改 filter 选项可以实现此目的。

  dta %>%
      group_by(id) %>% 
      arrange(desc(epnum)) %>%
      filter(!(id=='B13639J2' & row_number()==1L))

非常有帮助,谢谢。但是我需要检索rownumber以便删除它。 - giac
所以 row_number() 应该检索行号?谢谢。 - giac
1
我看到了 - 最后一件事非常抱歉 - 在这个 filter(id=='B13639J2', row_number()==1L) 上是否可能进行负过滤,使用 filter(id!='B13639J2', row_number()==1L) 是否可行?因为我需要摆脱这一行。非常感谢。 - giac
1
@giacomoV 你可以使用 anti_join 来移除它。 - akrun
1
@giacomoV,你几乎是对的。在“filter”中用“&”替换“,”,它就可以工作了。 - akrun
显示剩余4条评论

2

一种以环状基础R的方式来实现这个目标。暂时将不在所需组中的所有epnum值的副本设置为NA,然后运行which.max并删除结果行中的-

dta[-which.max(replace(dta$epnum, dta$id != "B13639J2", NA)),]

#            id epnum start
#95520 B13639J1     4   420
#95521 B13639J1     5   425
#95522 B13639J1     6   435
#95523 B13639J1     7   540
#95524 B13639J1     8   570
#95525 B13639J1     9  1000
#95526 B13639J1    10  1310
#95527 B13639J1    11  1325
#95528 B13639J2     1     0
#95529 B13639J2     2   860
#95530 B13639J2     3  1110
#95531 B13639J2     4  1155

这是由于which.max自动跳过所有的NANaN值造成的:
which.max(c(NA,1,NaN,2,3))
#[1] 5

这不会改变数据集的行顺序或删除任何rownames信息,而且运行速度相当快(在这里处理一个1000万行文件大约需要3秒)。


那是一个聪明的方式! - akrun

0

让我介绍另一个可能的解决方案。请告诉我您的想法。

首先,我为每个变量创建epnummax

dta = dta %>% 
  group_by(id) %>% 
  mutate(max = n())

然后,我只需对条件进行 ! 操作

dta[ !(dta$id == 'B13639J2' & (dta$epnum == dta$max)) , ]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接