在R中通过最大值和相同变量的附加条件对数据帧进行子集

时间:2018-03-11 15:53:09

标签: r

我是R的新人。希望这不是之前提出过的问题......

我正在尝试根据标准对数据框进行子集化:

一个。特定ID的最高价值

湾该值至少是同一ID列表中下一个值的两倍。

df看起来像这样(编辑过):

  > example_df_25
       df.qry.names        df.hit.len
1      10008                  407
2      10008                  181
3      10008                  166
4      10008                  160
5      10008                  146
6      10008                  145
7      10008                  120
8      10008                  101
9      10008                   96
10     10008                   93
11     10008                   85
12     10008                   83
13     10008                   83
14     10008                   58
15     10008                   56
16     10015                  462
17     10015                  350
18     10015                  193
19     10015                  160
20     10015                  154
21     10015                  152
22     10015                  138
23     10015                   66
24     10039                  501
25     10039                  406

我想得到的子集是:

 df.qry.names   hit.len 
  1 10008     407

这是一个dput(df)输出:

structure(list(df.qry.names = structure(c(1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 3L, 3L), .Label = c("10008", "10015", 
"10039"),class = "factor"), df.hit.len = c(407L, 
181L, 166L, 160L, 146L, 145L, 120L, 101L, 96L, 93L, 85L, 83L, 
83L, 58L, 56L, 462L, 350L, 193L, 160L, 154L, 152L, 138L, 66L, 
501L, 406L)), .Names = c("df.qry.names", "df.hit.len"
), row.names = c(NA, 25L), class = "data.frame") 

我理解如何基于data.table的最大值对df进行子集化,但是如何在第2个条件下得到它,它不仅仅是最大值,而是相关的两倍高下一个相同的ID?它一定是循环的吗? 希望有更快的解决方案...

谢谢!

2 个答案:

答案 0 :(得分:3)

使用dplyr,您可以执行以下操作: 按命中和命令按hit.len分组,将hit.len除以hit.len的前导并过滤大于或等于2的那些。

library(dplyr)
df1 %>% 
  group_by(id) %>% 
  arrange(id, desc(hit.len)) %>% 
  mutate(high = hit.len / lead(hit.len, n = 1L)) %>% 
  filter(high >= 2 ) %>% 
  select(id, hit.len)

# A tibble: 2 x 2
# Groups:   id [2]
     id hit.len
  <int>  <int>
1 10008    407
2 10029   1000

数据

df1 <- structure(list(id = c(10008L, 10008L, 10008L, 10008L, 10008L, 10008L, 10020L, 10020L, 10020L, 10029L, 10029L, 10029L), 
               hitlen = c(407L, 181L, 166L, 146L, 145L, 160L, 80L, 86L, 96L, 1000L, 87L, 111L)), 
          .Names = c("id", "hit.len"), 
          class = "data.frame", 
          row.names = c(NA, -12L))

答案 1 :(得分:1)

以下是data.table的解决方案:

library("data.table")

dt <- fread(
"id     hit.len 
10008     407    
10008     181    
10008     166    
10008     146    
10008     145    
10008     160
10020     80
10020     86
10020     96
10029    1000
10029    111
10029    87")
dt[, cond:= (hit.len==max(hit.len)) & (hit.len >= 2*shift(hit.len, type="lead")), by=id][(cond)]
#       id hit.len cond
# 1: 10008     407 TRUE
# 2: 10029    1000 TRUE

如果您希望最大值至少是第二个最大值的两倍,那么您可以先对data.table进行排序:

setorder(dt, id, -hit.len)

以下是效果type="lead"

的一个小例子
shift(1:5) # or shift(1:5, type="lag")
shift(1:5, type="lead") 

如果您有数据框df,可以通过以下方式将其强制转换为data.table-object:

setDT(df)

对于您的示例数据帧(dput):

df <- structure(list(df.qry.names = structure(c(1L, 1L, 1L, 
     1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
     2L, 2L, 2L, 2L, 3L, 3L), .Label = c("10008", "10015", 
       "10039"),class = "factor"), df.hit.len = c(407L,  
       181L, 166L, 160L, 146L, 145L, 120L, 101L, 96L, 93L, 85L, 83L, 
     83L, 58L, 56L, 462L, 350L, 193L, 160L, 154L, 152L, 138L, 66L, 
          501L, 406L)), .Names = c("df.qry.names", "df.hit.len"
              ), row.names = c(NA, 25L), class = "data.frame") 
###
library("data.table")
setDT(df)
df[, cond:= (df.hit.len==max(df.hit.len)) & (df.hit.len >= 2*shift(df.hit.len, type="lead")), by=df.qry.names][(cond)]