R:验证对应列值(ID 和名称)的匹配并标记不一致,最好在 dplyr 中
R: Validate matches of coresponding column values (ID and name) and flag inconsistencies, ideally in dplyr
假设您有一个包含数百个产品的数据框和另一个包含数千个销售额的数据框(请参阅下面的简化数据)。每个产品都有一个名称和一个 ID。不幸的是,在销售数据中,产品名称和 id 之间存在一些不一致(见观察 3)。我如何以自动方式识别和标记这些不一致,例如通过添加一个列来突出显示这些不一致(请参见下面的示例)。最好是集成到我的 dplyr 数据操作工作流程中。
请注意,数据有点乱,有些订单合并了多个产品(见obs.4)。我想到了与 grepl.
结合的循环
# products
P_names <- c( 'ProductA', 'ProductB')
P_ID <- c('p1', 'p2')
Product_list <- data.frame(P_names, P_ID)
P_names P_ID
1 ProductA p1
2 ProductB p2
# sales data
P_n_sales <- c('ProductA', 'ProductB', 'ProductB', 'ProductA, ProductB', 'ProductB, ProductA')
P_ID_sales <- c('p1', 'p2', 'p1', 'p1, p1', 'p1, p2')
sales_data <- data.frame(P_n_sales, P_ID_sales)
P_n_sales P_ID_sales
1 ProductA p1
2 ProductB p2
3 ProductB p1
4 ProductA, ProductB p1, p1
5 ProductB, ProductA p1, p2
期望的输出:
P_n_sales P_ID_sales Incons.
1 ProductA p1 corect
2 ProductB p2 corect
3 ProductB p1 error
4 ProductA, ProductB p1, p1 error
5 ProductB, ProductA p1, p2 correct
您可以执行 left/right 连接并将 Sales_data
中不存在的组合的值更改为 'error'
。
library(dplyr)
Sales_data %>%
mutate(rowid = row_number()) %>%
tidyr::separate_rows(P_n_sales, P_ID_sales, sep = ',\s*') %>%
left_join(Product_list %>% mutate(Incons = 'correct'),
by = c('P_n_sales' = 'P_names', 'P_ID_sales' = 'P_ID')) %>%
group_by(rowid) %>%
summarise(across(c(P_n_sales, P_ID_sales), toString),
Incons = if(any(is.na(Incons))) 'error' else 'correct') %>%
select(-rowid)
# P_n_sales P_ID_sales Incons
# <chr> <chr> <chr>
#1 ProductA p1 correct
#2 ProductB p2 correct
#3 ProductB p1 error
#4 ProductA, ProductB p1, p1 error
我想 %in%
就可以了
Sales_data %>% mutate(id = row_number()) %>%
separate_rows(P_n_sales, P_ID_sales) %>%
mutate(Incons. = paste(P_n_sales, P_ID_sales) %in% paste(Product_list$P_names, Product_list$P_ID)) %>%
group_by(id) %>%
summarise(Incons. = ifelse(min(Incons.) == 0, "Incorr", "Corr")) %>%
left_join(Sales_data %>% mutate(id = row_number()))
# A tibble: 4 x 4
id Incons. P_n_sales P_ID_sales
<int> <chr> <chr> <chr>
1 1 Corr ProductA p1
2 2 Corr ProductB p2
3 3 Incorr ProductB p1
4 4 Incorr ProductA, ProductB p1, p1
您好,感谢您的回复。然而,尽管上面提供的解决方案似乎 运行 快得多,但他们没有考虑到数据(产品 ID 和名称)可能以错误的顺序输入。
我更想找的是:
library(dplyr)
##
for (n in 1:nrow(Product_list)){
sales_data<-sales_data%>%
dplyr::mutate(Incons = ifelse(
(grepl(Product_list$P_names[n], sales_data$P_n_sales)
&!grepl(Product_list$P_ID[n], sales_data$P_ID_sales))
|
(!grepl(Product_list$P_names[n], sales_data$P_n_sales)
&grepl(Product_list$P_ID[n], sales_data$P_ID_sales))
,paste('error')
,paste('correct')
))
}
根据数据的复杂性,它可能需要在 grepl()
中进行额外的正则表达式规范,例如转义特殊字符、单词绑定、...
有没有人有比遍历数据更有效的方法(大数据需要相当长的时间)?
假设您有一个包含数百个产品的数据框和另一个包含数千个销售额的数据框(请参阅下面的简化数据)。每个产品都有一个名称和一个 ID。不幸的是,在销售数据中,产品名称和 id 之间存在一些不一致(见观察 3)。我如何以自动方式识别和标记这些不一致,例如通过添加一个列来突出显示这些不一致(请参见下面的示例)。最好是集成到我的 dplyr 数据操作工作流程中。
请注意,数据有点乱,有些订单合并了多个产品(见obs.4)。我想到了与 grepl.
结合的循环# products
P_names <- c( 'ProductA', 'ProductB')
P_ID <- c('p1', 'p2')
Product_list <- data.frame(P_names, P_ID)
P_names P_ID
1 ProductA p1
2 ProductB p2
# sales data
P_n_sales <- c('ProductA', 'ProductB', 'ProductB', 'ProductA, ProductB', 'ProductB, ProductA')
P_ID_sales <- c('p1', 'p2', 'p1', 'p1, p1', 'p1, p2')
sales_data <- data.frame(P_n_sales, P_ID_sales)
P_n_sales P_ID_sales
1 ProductA p1
2 ProductB p2
3 ProductB p1
4 ProductA, ProductB p1, p1
5 ProductB, ProductA p1, p2
期望的输出:
P_n_sales P_ID_sales Incons.
1 ProductA p1 corect
2 ProductB p2 corect
3 ProductB p1 error
4 ProductA, ProductB p1, p1 error
5 ProductB, ProductA p1, p2 correct
您可以执行 left/right 连接并将 Sales_data
中不存在的组合的值更改为 'error'
。
library(dplyr)
Sales_data %>%
mutate(rowid = row_number()) %>%
tidyr::separate_rows(P_n_sales, P_ID_sales, sep = ',\s*') %>%
left_join(Product_list %>% mutate(Incons = 'correct'),
by = c('P_n_sales' = 'P_names', 'P_ID_sales' = 'P_ID')) %>%
group_by(rowid) %>%
summarise(across(c(P_n_sales, P_ID_sales), toString),
Incons = if(any(is.na(Incons))) 'error' else 'correct') %>%
select(-rowid)
# P_n_sales P_ID_sales Incons
# <chr> <chr> <chr>
#1 ProductA p1 correct
#2 ProductB p2 correct
#3 ProductB p1 error
#4 ProductA, ProductB p1, p1 error
我想 %in%
就可以了
Sales_data %>% mutate(id = row_number()) %>%
separate_rows(P_n_sales, P_ID_sales) %>%
mutate(Incons. = paste(P_n_sales, P_ID_sales) %in% paste(Product_list$P_names, Product_list$P_ID)) %>%
group_by(id) %>%
summarise(Incons. = ifelse(min(Incons.) == 0, "Incorr", "Corr")) %>%
left_join(Sales_data %>% mutate(id = row_number()))
# A tibble: 4 x 4
id Incons. P_n_sales P_ID_sales
<int> <chr> <chr> <chr>
1 1 Corr ProductA p1
2 2 Corr ProductB p2
3 3 Incorr ProductB p1
4 4 Incorr ProductA, ProductB p1, p1
您好,感谢您的回复。然而,尽管上面提供的解决方案似乎 运行 快得多,但他们没有考虑到数据(产品 ID 和名称)可能以错误的顺序输入。
我更想找的是:
library(dplyr)
##
for (n in 1:nrow(Product_list)){
sales_data<-sales_data%>%
dplyr::mutate(Incons = ifelse(
(grepl(Product_list$P_names[n], sales_data$P_n_sales)
&!grepl(Product_list$P_ID[n], sales_data$P_ID_sales))
|
(!grepl(Product_list$P_names[n], sales_data$P_n_sales)
&grepl(Product_list$P_ID[n], sales_data$P_ID_sales))
,paste('error')
,paste('correct')
))
}
根据数据的复杂性,它可能需要在 grepl()
中进行额外的正则表达式规范,例如转义特殊字符、单词绑定、...
有没有人有比遍历数据更有效的方法(大数据需要相当长的时间)?