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

在R中为指定条目多列查找多字符串并返回列名

问题描述

我需要在R语言中处理一个数据框,要求针对每个Item_Name条目,在Sample_A、Sample_B等多列里查找包含"0/1"或"1/1"的字符串,并返回对应的列名。目前我只会用grepl单次查找一个模式,也不清楚如何获取符合条件的列名,现有代码如下:

data_frame_mod  <- dataframe[Reduce(`|`, lapply(dataframe, grepl, pattern = "0/1"))]
解决方法

你的现有代码是用来筛选出至少有一列包含"0/1"的行,而非提取每行对应的符合条件的列名。以下是两种实用的实现方案:

方法1:基础R的apply函数

先构造示例数据框用于演示:

# 示例数据框
dataframe <- data.frame(
  Item_Name = c("Item1", "Item2", "Item3"),
  Sample_A = c("0/0", "0/1", "1/1"),
  Sample_B = c("1/1", "0/0", "0/1"),
  Sample_C = c("0/0", "1/1", "0/0"),
  stringsAsFactors = FALSE
)

通过apply逐行处理,提取符合条件的列名:

# 定义匹配规则:同时匹配"0/1"或"1/1"
pattern <- "(0/1|1/1)"

# 逐行提取匹配列名并整理为数据框
result <- data.frame(
  Item_Name = dataframe$Item_Name,
  Matching_Samples = apply(dataframe[, -1], 1, function(row) {
    # 获取当前行中符合匹配规则的列名,用逗号分隔
    paste(names(row)[grepl(pattern, row)], collapse = ", ")
  })
)

print(result)

输出结果:

Item_Name Matching_Samples
1     Item1        Sample_B
2     Item2 Sample_A, Sample_C
3     Item3 Sample_A, Sample_B

方法2:tidyverse风格(dplyr+tidyr)

如果习惯使用tidyverse工具链,这种写法更直观,还能处理无匹配的情况:

library(dplyr)
library(tidyr)

result <- dataframe %>%
  # 将宽数据转为长数据,方便筛选
  pivot_longer(cols = starts_with("Sample_"), names_to = "Sample", values_to = "Genotype") %>%
  # 筛选出符合匹配规则的行
  filter(grepl(pattern, Genotype)) %>%
  # 按Item_Name分组,合并对应的列名
  group_by(Item_Name) %>%
  summarise(Matching_Samples = paste(Sample, collapse = ", ")) %>%
  # 补全所有Item_Name条目,无匹配的标记为"无匹配"
  right_join(dataframe %>% select(Item_Name), by = "Item_Name") %>%
  replace_na(list(Matching_Samples = "无匹配"))

print(result)

关键说明

  • 正则表达式"(0/1|1/1)"实现了同时匹配两种目标字符串,grepl默认支持正则语法,|表示“或”的逻辑关系。
  • 获取列名的核心逻辑是:先定位每行中符合条件的列位置,再用names()提取对应列名,最后合并为字符串格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:42:14