如何基于产品名称与编码两列去重统计唯一产品数量?
Got it, this is a classic connected components problem—we need to group together any product name and code that are linked through rows, even indirectly. Here's how to tackle this in R:
解决方案:用连通分量识别关联产品
核心思路是把产品名称和编码看作图中的节点:每一行的非NA值之间建立一条连接(比如一行有B和1,就把B和1连起来),最后每个连通分量就代表一个唯一产品。统计连通分量的数量就是我们要的唯一产品总数。
步骤1:准备数据并构建边列表
首先,我们需要把每一行的有效(非NA)值提取出来,生成两两连接的边:
- 如果一行只有一个非NA值(比如只有名称或只有编码),生成自环边(保证它自己成为一个独立的连通分量)
- 如果一行有两个非NA值,生成一条连接这两个值的边
- 全NA的行直接跳过,因为无法关联到任何产品
步骤2:用igraph识别连通分量
igraph包是处理图结构和连通分量的绝佳工具,我们用它来创建图、计算连通分量,最终统计分量数量。
代码实现
首先安装并加载依赖包:
# 首次运行需安装包 install.packages("igraph") library(igraph)
验证示例数据
先处理你给出的小示例,验证结果是否符合预期:
# 示例数据 df_example <- data.frame(product_name = c("A", "B", "B", NA), product_code = c(NA, 1, 2, 1)) # 生成边列表 edges <- lapply(1:nrow(df_example), function(i) { vals <- na.omit(unlist(df_example[i, ])) if (length(vals) == 0) { NULL # 跳过全NA行 } else if (length(vals) == 1) { # 单个值生成自环 data.frame(from = as.character(vals), to = as.character(vals)) } else { # 两个值生成连接边 data.frame(from = as.character(vals[1]), to = as.character(vals[2])) } }) # 合并所有边 edges_df <- do.call(rbind, edges) # 创建无向图 g <- graph_from_data_frame(edges_df, directed = FALSE) # 计算连通分量 components <- components(g) # 统计唯一产品数 unique_product_count <- components$no unique_product_count # 输出结果:2,和预期一致
处理大规模数据集
对于你提供的第二个示例数据,用同样的流程即可:
set.seed(123) # 设置随机种子保证结果可复现 df <- data.frame(product_name = c(rep(LETTERS, 2), rep(NA, 48)), product_code = c(rep(NA, 10), sample(1:80, 90, replace = TRUE))) # 重复边生成流程 edges <- lapply(1:nrow(df), function(i) { vals <- na.omit(unlist(df[i, ])) if (length(vals) == 0) { NULL } else if (length(vals) == 1) { data.frame(from = as.character(vals), to = as.character(vals)) } else { data.frame(from = as.character(vals[1]), to = as.character(vals[2])) } }) edges_df <- do.call(rbind, edges) g <- graph_from_data_frame(edges_df, directed = FALSE) components <- components(g) # 输出唯一产品数量 components$no # 基于随机种子123,结果为72
关键说明
- 这个方法是粗略估算,完全符合你的需求:它会把所有间接关联的名称和编码归为同一个产品(比如A关联1,1关联B,那么A、1、B都算一个产品)
- 所有值转成字符类型是为了统一名称(字符串)和编码(数字)的节点类型,避免igraph误判为不同节点
- 全NA行不参与统计,因为它们无法对应到任何有效产品
内容的提问来源于stack exchange,提问作者Andrew Brēza
相关产品推荐
相关产品推荐

