匹配列并找到不匹配的值
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, 300
和 300, 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))))
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, 300
和 300, 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))))