r - R:比较同一数据帧内的 ID
问题描述
我有以下数据集:
df <- data.frame(c(1,1,1,2,2,2,2,3,3,3,3,4,4,4,5,5,5), c("a","a","a","b","b","b","b","b","b","b","b",
"a","a","a","b","b","b"),
c(300,295,295,25,25,25,25,25,20,20,20,300,295,295,300, 295,295),
c("c","d","e","f","g","h","i","j","l","m","n","o","p","q","r","s","t"))
colnames(df) <- c("ID", "Group", "Price", "OtherNumber")
> df
ID Group Price OtherNumber
1 1 a 300 c
2 1 a 295 d
3 1 a 295 e
4 2 b 25 f
5 2 b 25 g
6 2 b 25 h
7 2 b 25 i
8 3 b 25 j
9 3 b 20 l
10 3 b 20 m
11 3 b 20 n
12 4 a 300 o
13 4 a 295 p
14 4 a 295 q
15 5 b 300 r
16 5 b 295 s
17 5 b 295 t
我想比较后续ID的第一个价格。仅当后续的两个ID具有相同的初始价格并且在同一组中时,我才想标记它们。以防万一这不是很清楚,这里有一个例子:我比较第一个和第二个 ID,但组(a 与 b)和初始价格不匹配(300 与 25)。另一方面,在 ID 2 和 3 之间,它们都在 b 组中并且具有相同的初始价格 25(参见第 4 行和第 8 行)。之后的价格并不重要,因为它们可能会有所不同。
我想,我必须能够使用 dplyr 包并确定了一个非常粗略的解决方案(这还不起作用)。
# Load dplyr
library(dplyr)
# Assign row numbers within IDs
df1 <- df %>%
group_by(ID) %>%
mutate(subID = row_number())
# Isolate first observation in ID
df2 <- df1[df1$subID == 1,]
# Set up loop to iterate through IDs
for (i in 2:length(df2)) {
if (df2$Price[i] - df2$Price[i - 1] == 0) {
df2$flag <- TRUE
} else {
df2$flag <- FALSE
}
}
如果您告诉我这是唯一可能的解决方案,我显然会为此投入更多资源,但我确信一定有更简单的解决方案。我检查了 SO,也许我错过了一些东西,但我找不到任何朝着这个方向发展的东西。谢谢!
我想得到的输出看起来像这样:
ID Group Price OtherNumber flag
1 1 a 300 c FALSE
2 1 a 295 d FALSE
3 1 a 295 e FALSE
4 2 b 25 f TRUE
5 2 b 25 g TRUE
6 2 b 25 h TRUE
7 2 b 25 i TRUE
8 3 b 25 j TRUE
9 3 b 20 l TRUE
10 3 b 20 m TRUE
11 3 b 20 n TRUE
12 4 a 300 o FALSE
13 4 a 295 p FALSE
14 4 a 295 q FALSE
15 5 b 300 r FALSE
16 5 b 295 s FALSE
17 5 b 295 t FALSE
解决方案
这里是一个data.table oneliner……切小块查看中间结果;另请参阅答案底部的解释。
dt <- as.data.table( df )
dt[ dt[ , .SD[1], ID][ ( Group == shift( Group, type = "lead") & Price == shift( Price, type = "lead") ) |
( Group == shift( Group, type = "lag") & Price == shift( Price, type = "lag),
flag := TRUE][is.na(flag), flag := FALSE], flag := i.flag, on = .(ID)][]
# ID Group Price OtherNumber flag
# 1: 1 a 300 c FALSE
# 2: 1 a 295 d FALSE
# 3: 1 a 295 e FALSE
# 4: 2 b 25 f TRUE
# 5: 2 b 25 g TRUE
# 6: 2 b 25 h TRUE
# 7: 2 b 25 i TRUE
# 8: 3 b 25 j TRUE
# 9: 3 b 20 l TRUE
# 10: 3 b 20 m TRUE
# 11: 3 b 20 n TRUE
# 12: 4 a 300 o FALSE
# 13: 4 a 295 p FALSE
# 14: 4 a 295 q FALSE
# 15: 5 b 300 r FALSE
# 16: 5 b 295 s FALSE
# 17: 5 b 295 t FALSE
解释:
dt[ , .SD[1], ID]
创建一个data.table,每个的第一行ID
[ Group == shift( ... , flag := TRUE]
将列设置flag
为TRUE
下一个(或上一个)行匹配Price
和 Group
。
[is.na(flag), flag := FALSE]
用 `FALSE 填充其余部分(不是 TRUE)
..flag := i.flag, on = .(ID)]
对原始 data.table 执行左连接(通过引用,因此快速高效),以获得最终结果。
推荐阅读
- python - 使用 Selenium (Python) 从输出框中获取值
- html - MVC Razor 视图显示 DateTime 对象的错误时间值
- c# - C# If Else 语句返回不同的 MessageBox 错误
- python-2.7 - 字典到表格形式
- c# - 如何正确定义 EF Core 创建的这些类之间的关系?
- python-3.x - 在 Python 3 上将不同类型的信息写入 2 个不同的日志文件?
- java - 带有打包依赖项的 Maven 构建 jar
- docker - docker-compose.yml 中另一个变量中的用户变量如何
- php - 获取每张图片的具体记录
- r - 计算单词的长度并切割低于阈值的行