如何根据多个by-record标准从data.table中提取特定字段?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何根据多个by-record标准从data.table中提取特定字段?相关的知识,希望对你有一定的参考价值。
使用q的data.table包,我希望能够根据多个标准提取特定记录。实际上,我正在处理一个包含数百万或数千万条记录的表,并且我想提取给定字段的倒数第二个条目,以获得在该字段中终止0个条目的记录。我可以确定哪些记录是感兴趣的,并且我可以识别0条目的日期,因此通过一些创造性地使用lubridate,我可以创建一个ID列表和“我应该寻找的日期”。如何使用这个两列100行列表并使用它从1000万条记录表中返回我需要的特定100个值?
这是我想要做的一个简单的例子。
鉴于以下数据表A
:
Name Date Amount
1: A 1 100
2: A 2 100
3: A 3 100
4: A 4 99
5: A 5 98
6: A 6 97
7: A 7 96
8: A 8 95
9: A 9 94
10: A 10 93
11: A 11 92
12: A 12 0
13: B 2 200
14: B 3 200
15: B 4 190
16: B 5 180
17: B 6 170
18: B 7 160
19: B 8 150
20: B 9 0
21: C 2 100
22: C 3 95
23: C 4 90
24: C 5 90
25: C 6 85
26: C 7 80
27: C 8 0
我想做的是为每条记录拉最后一个非零的Amount
。我能做的是创建一个表B
:
Name Date
1: A 11
2: B 8
3: C 7
我想要的是Amount
中的A
,Name
中的每个Date
和B
。答案应该是c(92, 150, 80)
。
另一种方法是提取所有记录的子集,使得Name
和Date
字段对有效。我可以连接这两个并搜索这种方式,但实际上,Name
是一个长字母数字字符串,而Date
被转换为POSIX,因此可能会变得难看。
此外,我可能会以错误的方式执行此操作,如果有一种更简单的方法可以返回特定字段的倒数第二条记录,这可能是我需要的全部功能,例如:A[Name %in% X, second-to-last record, by = Name]
其中X
是其中的记录列表我有兴趣。
谢谢。
码
A <- structure(list(Name = c("A", "A", "A", "A", "A", "A", "A", "A",
"A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "C",
"C", "C", "C", "C", "C", "C"), Date = c(1L, 2L, 3L, 4L, 5L, 6L,
7L, 8L, 9L, 10L, 11L, 12L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 2L,
3L, 4L, 5L, 6L, 7L, 8L), Amount = c(100L, 100L, 100L, 99L, 98L,
97L, 96L, 95L, 94L, 93L, 92L, 0L, 200L, 200L, 190L, 180L, 170L,
160L, 150L, 0L, 100L, 95L, 90L, 90L, 85L, 80L, 0L)), .Names = c("Name",
"Date", "Amount"), row.names = c(NA, -27L), class = c("data.table",
"data.frame"))
B <- data.table(Name = c('A', 'B', 'C'), Date = c(11, 8, 7))
无需创建单独的qazxsw poi data.table。您可以过滤掉零值,然后选择最后一个观察值。有几种方法可以做到这一点:
B
这些都给了:
# method 1:
A[Amount!=0, tail(.SD,1), by = Name]
# method 2:
A[!!Amount, .SD[.N], by = Name]
# method 3:
A[Amount!=0, lapply(.SD, last), by = Name]
# method 4:
A[Amount!=0][!duplicated(Name, fromLast = TRUE)]
# method 5 (as proposed by @Frank in the comments):
unique(A[Amount!=0], by = "Name", fromLast = TRUE)
# method 6:
A[A[Amount!=0, .I[.N], Name]$V1]
笔记:
Name Date Amount 1: A 11 92 2: B 8 150 3: C 7 80
将无法正常工作并导致错误消息。- 方法6可能看起来过于复杂,但尤其是在非常大的数据集上,使用
A[Amount!=0, last(.SD), by = Name]
似乎是最快的方法。有关基准测试,请参阅.I
。
关于您的第二个问题(如this answer中所述),您可以使用如下连接来获取特定日期的值:
the comments
这给你:
B <- data.table(Name = c('A', 'B', 'C'), Date = c(5, 4, 6))
A[B, on = c('Name','Date')]
# or as proposed by @Frank:
A[B, on = names(B)]
以上是关于如何根据多个by-record标准从data.table中提取特定字段?的主要内容,如果未能解决你的问题,请参考以下文章