You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R语言的apply函数中添加条件语句的实现问题

需求:按c1分组匹配同组内c2阈值相近的c3值

原功能函数

现有基于apply和outer实现的函数,可判断df中每行c2与其他行c2的差值绝对值是否小于1e7,返回匹配行的c3列ID:

df$match <- apply(outer(df$c2, df$c2, function(x, y) abs(x - y) <  1e7) &
                       diag(nrow(df)) == 0, 
                       MARGIN = 1,
                       function(x) paste(df$c3[x], collapse = ", "))

现有数据

c1     c2         c3                 match
1      52426577   chr1.52426577_T    chr2.43668478_G, chr2.47207905_G, chr2.47959251_C, chr2.49606475_C
1      108023890  chr1.108023890_A   
1      129776943  chr1.129776943_T   
2      39943710   chr2.39943710_C    chr2.43668478_G, chr2.47207905_G, chr2.47959251_C, 
2      43668478   chr2.43668478_G    chr1.52426577_T, chr2.39943710_C, chr2.47207905_G, chr2.47959251_C
2      47207905   chr2.47207905_G    chr1.52426577_T, chr2.39943710_C, chr2.43668478_G, chr2.47959251_C
2      47959251   chr2.47959251_C    chr1.52426577_T, chr2.39943710_C, chr2.43668478_G, chr2.47207905_G

尝试修改后的错误代码

尝试添加条件仅比较c1列相同的行,运行报错attempt to apply non-function:

df$match <- apply(outer(df$c2, df$c2, function(x, y) if(df$c1(x) == df$c1(y)) abs(x - y) <  1e7) &
                       diag(nrow(df)) == 0, 
                       MARGIN = 1,
                       function(x) paste(df$c3[x], collapse = ", "))

尝试dplyr分组的错误代码

用dplyr分组实现时同样报错:

df$match <- sapply(df$c3, function(x){
  df %>%
    group_by(c1) %>%
    filter(abs(c2 - c2[c3 == x]) < 1e7,
           c3 != x) %>%
    pull(c3) %>%
    paste0(collapse = ',')
})

报错信息:

Error in `filter()`:
! Problem while computing `..1 = abs(d2 - d2[d3 == x]) < 1e+07`.
✖ Input `..1` must be of size 17 or 1, not size 0.
ℹ The error occurred in group 2: d1 = 2.

期望结果

仅在c1相同的行内匹配,得到如下结果:

c1     c2         c3                 match
1      52426577   chr1.52426577_T    
1      108023890  chr1.108023890_A   
1      129776943  chr1.129776943_T   
2      39943710   chr2.39943710_C    chr2.43668478_G, chr2.47207905_G, chr2.47959251_C 
2      43668478   chr2.43668478_G    chr2.39943710_C, chr2.47207905_G, chr2.47959251_C
2      47207905   chr2.47207905_G    chr2.39943710_C, chr2.43668478_G, chr2.47959251_C
2      47959251   chr2.47959251_C    chr2.39943710_C, chr2.43668478_G, chr2.47207905_G

解决方法

方法1:修正原apply+outer逻辑

原错误是df$c1(x)的写法错误,需通过索引取对应行的c1值。正确逻辑是先构建c1匹配矩阵,再与c2阈值矩阵结合:

# 构建c1相同的矩阵:同组为TRUE,不同组为FALSE
c1_match <- outer(df$c1, df$c1, `==`)
# 构建c2差值小于阈值的矩阵
c2_match <- outer(df$c2, df$c2, function(x, y) abs(x - y) < 1e7)
# 排除自身匹配(对角线设为FALSE)
no_self <- !diag(nrow(df))

# 合并条件:c1相同 + c2阈值匹配 + 非自身
df$match <- apply(c1_match & c2_match & no_self, MARGIN = 1, function(x) {
  paste(df$c3[x], collapse = ", ")
})

方法2:dplyr分组修正版

原dplyr代码问题在于分组内索引匹配逻辑混乱,改为按c1分组后,针对每组内每行匹配同组其他符合条件的行:

library(dplyr)
library(purrr)

df <- df %>%
  group_by(c1) %>%
  mutate(match = map_chr(row_number(), function(i) {
    target_c2 <- c2[i]
    # 同组内排除自身,且c2差值小于阈值的c3值
    matches <- c3[c2 != target_c2 & abs(c2 - target_c2) < 1e7]
    paste(matches, collapse = ", ")
  })) %>%
  ungroup()

两种方法均可得到期望结果:c1=1组内无符合阈值的匹配,match为空;c1=2组内每行均能匹配到同组其他符合条件的c3值。


内容的提问来源于stack exchange,提问作者Melderon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:25:21