如何创建一个列来计算一系列行的两列之间的差异,这些行的其他两列具有匹配的值

问题描述 投票:0回答:1

我一直在尝试使用 dplyr、strigr 和 grepl 创建一个新列,用于计算数据集中的列之间的差异,该数据集中具有两个列变量中具有匹配值的配对列和其他两列的不同值,其中一列是我想要计算差异的兴趣之一。

行集的匹配值为“日期”和“时间”,行集的不匹配值为“Context”和“IndividualID”。

我想要创建的新列将应用于具有上述匹配值(日期、时间)的行集中的 individualID 之间的差异。

这是数据集的样子,

Date        Time  Context    SeriesNumber IndividualID
01/01/2000  8.00  Mixed       1           a, b, c, d, e, f
01/01/2000  8.00  NON_Mixed   1           d, e, f, g, h
01/01/2000  9.00  Mixed       2           c, d, e, f
01/01/2000  9.00  NON_Mixed   2           a, b, c, d
01/01/2000  9.00  NON_Mixed   2           e, f, g, h

因此新列将是IndividualID_Difference,并且只会针对非混合上下文进行计算,对于混合上下文,它应该保持不变。

Date        Time  Context   SeriesNumber  IndividualID       IndividualID_Difference
01/01/2000  8.00  Mixed      1            a, b, c, d, e, f   a, b, c, d, e, f  
01/01/2000  8.00  NON_Mixed  1            d, e, f, g, h      g, h
01/01/2000  9.00  Mixed      2            c, d, e, f         c, d, e, f
01/01/2000  9.00  NON_Mixed  2            a, b, c, d         a, b
01/01/2000  9.00  NON_Mixed  2            e, f, g, h         g, h

第二行 d、e、f 被删除,因为它们出现在混合上下文的匹配行(第一行具有相同的时间、日期和系列号,但不同的上下文)中,它们在非混合中重复,即为什么需要删除它们。

在第四行中,a、b 被删除,因为它们出现在第三行中,即具有相同时间、日期和系列号以及不同上下文的匹配行。

在第五行中,e、f 被删除,因为它们出现在第三行中,即具有相同时间、日期和 SeriesNumber 以及不同上下文的匹配行。

IndividualID 列表相当庞大。

如果您知道如何为这个棘手的问题找到解决方案,谢谢!

r dplyr group-by stringr mutate
1个回答
0
投票

我希望有一种不太复杂的方法来实现这一目标,但我无法弄清楚如何以其他方式做到这一点。由于我们没有您的数据的

dput()
,我假设您的IndividualID 列是字符类型。因此,此方法涉及将您的IndividualID 转换为列表类型列,并为每个组创建“混合”IndividualID 的列表类型列。然后比较这两列之间的差异并返回差异。

此方法还假设“混合”值始终是每组的第一行。如果我的两个假设都不正确,请告诉我,我会更新我的答案。

library(dplyr)
library(stringr)

# Your sample data
df <- read.table(text = "Date;Time;Context;SeriesNumber;IndividualID
01/01/2000;8.00;Mixed;1;a, b, c, d, e, f
01/01/2000;8.00;NON_Mixed;1;d, e, f, g, h
01/01/2000;9.00;Mixed;2;c, d, e, f
01/01/2000;9.00;NON_Mixed;2;a, b, c, d
01/01/2000;9.00;NON_Mixed;2;e, f, g, h", sep = ";", header = TRUE)

# Add list versions of both IndividualID and the "mixed" variable of 
# IndividualID to new temp columns
df1 <- df %>%
  rowwise() %>%
  mutate(temp1 = list(strsplit(IndividualID,", "))) %>%
  group_by(SeriesNumber) %>%
  mutate(temp2 = list(strsplit(IndividualID[1],", "))) %>%
  ungroup() 

# Function to compare new list columns and return desired results
unmatched_chars <- function(x, y, z) {
  ind_chars <- str_split(x, ", ")[[1]]
  res_chars <- setdiff(ind_chars, unlist(z))
  paste(res_chars, collapse = ", ")
}

# Use unmatched_chars function to create IndividualID_Difference
df1 <- df1 %>%
  rowwise() %>%
  mutate(IndividualID_Difference = unmatched_chars(IndividualID, 
                                                   temp1,
                                                   temp2),
         IndividualID_Difference = ifelse(IndividualID_Difference == "", 
                                          IndividualID, 
                                          IndividualID_Difference)) %>%
  select(-starts_with("temp"))

data.frame(df1)
        Date Time   Context SeriesNumber     IndividualID IndividualID_Difference
1 01/01/2000    8     Mixed            1 a, b, c, d, e, f        a, b, c, d, e, f
2 01/01/2000    8 NON_Mixed            1    d, e, f, g, h                    g, h
3 01/01/2000    9     Mixed            2       c, d, e, f              c, d, e, f
4 01/01/2000    9 NON_Mixed            2       a, b, c, d                    a, b
5 01/01/2000    9 NON_Mixed            2       e, f, g, h                    g, h
© www.soinside.com 2019 - 2024. All rights reserved.