如何根据多个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中的AName中的每个DateB。答案应该是c(92, 150, 80)

另一种方法是提取所有记录的子集,使得NameDate字段对有效。我可以连接这两个并搜索这种方式,但实际上,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]

笔记:

  1. Name Date Amount 1: A 11 92 2: B 8 150 3: C 7 80 将无法正常工作并导致错误消息。
  2. 方法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中提取特定字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据应用于大量列的“不等于”标准对数据框进行子集化?

将excel根据列名称拆分成多个文件

INDEX MATCH 根据日期范围和名称标准返回多个结果

根据多个标准检索和排序结果

如何根据多个条件从 SQL Server 中删除大量数据

使用密钥基于多个标准寻求excel公式