匹配列并找到不匹配的值

Matching columns and finding the unmatched value

df <- data.frame(A = c('100, 200, 300, 100', '100, 200', '100, 200, 300'), B = c('100, 200, 300', '100, 200, 300', '100, 200'), stringsAsFactors = FALSE) 我这里有一个数据框示例

我要做比较,结果在'Flag.'栏中可以找到,如果完全匹配,则Flag为Y,否则为N,如果Flag为N,则我'确定缺失值是什么。以第 2 行为例:A 列中缺少 300,因此我将其填充在值 A 下。

虽然很乱,但它会得到你想要的。

library(dplyr)
  df1 <- data.frame(
    A = c("100,200,300", "100,200", "100,200,400"),
    B = c("100,200,300", "100,200,300", "100,200")
  )
  isEmpty <- function(x) {
    return(length(x)==0)
  }
df1 <- df1 %>%
  mutate(A = as.character(A),
         B = as.character(B)) %>%
  mutate(Flag = ifelse(A == B, "Y", "N"))

df2 <- apply(df1, 1, function(x){
  if (x[3] == "N"){
    a <- x[1] %>% strsplit(., ",") %>% unlist %>% as.numeric()
    b <- x[2] %>% strsplit(., ",") %>% unlist %>% as.numeric()
    val_A <- ifelse(isEmpty(setdiff(a,b)), "A", setdiff(a,b))
    val_B <- ifelse(isEmpty(setdiff(b,a)), "A", setdiff(b,a))
    c(val_A,val_B)
  } else {
    c(NA,NA)
  }
}) %>% t %>% as.data.frame() %>% dplyr::rename(Value_A = V1, Value_B = V2)
cbind(df1, df2)

            A           B Flag Value_A Value_B
1 100,200,300 100,200,300    Y    <NA>    <NA>
2     100,200 100,200,300    N       A     300
3 100,200,400     100,200    N     400       A

您可以用逗号分隔 A 列和 B 列,然后比较它们以获得输出。

library(dplyr)
library(purrr)

df %>%
  mutate(across(A:B, strsplit, ',\s*'), 
         Flag = map2_chr(A, B, ~if(all(.x %in% .y) && all(.y %in% .x)) 'Y' else 'N'),
         ColumnA = map2_chr(A, B, ~toString(setdiff(.y, .x))), 
         ColumnB = map2_chr(A, B, ~toString(setdiff(.x, .y))))

#              A             B Flag ColumnA ColumnB
#1 100, 200, 300 100, 200, 300    Y                
#2      100, 200 100, 200, 300    N     300        
#3 100, 200, 300      100, 200    N             300

对于这个例子,要得到 Flag 列,我们可以只做 Flag = ifelse(A == B, 'Y', 'N') 但是如果你有像 100, 200, 300300, 200, 100 这样的值怎么办 [=16] =] 会 return 'N' 因此我更喜欢拆分和比较。


对于计数也很重要的更新数据,我们可以使用 vecsets 包中的 vsetdiff 函数。

library(vecsets)

df %>%
  mutate(across(A:B, strsplit, ',\s*'), 
         Flag = map2_chr(A, B, ~if(all(.x %in% .y) && all(.y %in% .x)) 'Y' else 'N'),
         ColumnA = map2_chr(A, B, ~toString(vsetdiff(.y, .x))), 
         ColumnB = map2_chr(A, B, ~toString(vsetdiff(.x, .y))))