在R中如何用0填充缺失值实现非兼容数组的逐元素相乘?
问题
我想实现非兼容数组的逐元素相乘,本以为简单却卡壳了。现有两个表格:
table_a
chr1 chr2 chr3 5 5 5
table_b
chr1 chr2 5 5
期望逐元素相乘后得到:
table_c
chr1 chr2 chr3 25 25 0
用table_a * table_b在元素数量相同时可行,但没法处理数量不同的情况。试过转成数据框、用cbind/merge及各种连接方法,都没解决。希望尽量用base R或dplyr这类可靠库,求最简实现方案!
我的代码:
# 生成bed数据 start1 <- seq(105000, 200000, by=20000) stop1 <- start1+2000 chrs <- c("chr1", "chr2", "chr3") x <- sort(rep(chrs, times=5)) df_a <- data.frame(chr=x, start=rep(start1,times=3), stop=rep(stop1,times=3)) start2 <-seq(800000, 920000, by=25000) stop2 <- start2+2000 df_b <- data.frame(chr=x, start=rep(start2,times=3), stop=rep(stop2, times=3)) # 移除bed中的一个染色体 df_b <- df_b[1:10,] table_a <- table(df_a[,1]) table_b <- table(df_b[,1])
解决方案
方法一:base R实现
核心思路是统一两个表格的名称集合,缺失项补0后再做逐元素相乘,最后转回table格式:
# 转成命名向量 vec_a <- as.numeric(table_a) names(vec_a) <- names(table_a) vec_b <- as.numeric(table_b) names(vec_b) <- names(table_b) # 获取所有唯一染色体名称 all_chrs <- union(names(vec_a), names(vec_b)) # 补全缺失的染色体,值设为0 vec_a_full <- ifelse(all_chrs %in% names(vec_a), vec_a[all_chrs], 0) vec_b_full <- ifelse(all_chrs %in% names(vec_b), vec_b[all_chrs], 0) names(vec_a_full) <- all_chrs names(vec_b_full) <- all_chrs # 相乘后转回table table_c <- table(factor(all_chrs, levels = all_chrs)) table_c[] <- vec_a_full * vec_b_full table_c
执行结果:
chr1 chr2 chr3 25 25 0
方法二:dplyr实现
利用数据框全连接补全缺失项,再计算乘积:
library(dplyr) # 把table转成带列名的数据框 df_table_a <- as.data.frame(table_a) %>% rename(chr = Var1, count_a = Freq) df_table_b <- as.data.frame(table_b) %>% rename(chr = Var1, count_b = Freq) # 全连接补0,计算乘积后转回table table_c <- full_join(df_table_a, df_table_b, by = "chr") %>% mutate( count_a = replace(count_a, is.na(count_a), 0), count_b = replace(count_b, is.na(count_b), 0), product = count_a * count_b ) %>% select(chr, product) %>% tibble::deframe() %>% table() table_c
同样能得到目标输出。
内容的提问来源于stack exchange,提问作者Doda
相关产品推荐
相关产品推荐

