【问题标题】:R: Compare across IDs within the same data frameR:比较同一数据帧内的 ID
【发布时间】:2019-07-26 01:49:23
【问题描述】:

我有以下数据集:

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

【问题讨论】:

    标签: r dataframe group-by dplyr


    【解决方案1】:

    这里是一个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 进行左连接(通过引用,因此快速高效),得到最终结果。

    【讨论】:

    • 谢谢,正是我想要的(也感谢您的详细解释)!只是一个简短的评论:如果我没记错的话,在两个匹配行中的任何一个中,它应该是滞后而不是领先。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2021-09-16
    • 2020-11-07
    相关资源
    最近更新 更多