我是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?它一定是循环的吗? 希望有更快的解决方案...
谢谢!
答案 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)
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)]