You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

R语言中如何逐行获取仅含0和1的矩阵中多个1的列索引或列名?

嗨,我来帮你搞定这个需求!你需要从0-1矩阵里提取每行中1对应的列索引或列名,而且每行的1数量还不一样,对吧?这里有几种实用的R实现方案,都能完美适配你的场景:

方法1:用apply()逐行处理(直观易读)

这是最直接的方式,对矩阵的每一行应用自定义函数,筛选出值为1的列位置:

set.seed(444)
m3 <- matrix(round(runif(8*8)), 8,8)

# 提取每行1对应的列索引
row_ones_indices <- apply(m3, 1, function(x) which(x == 1))

# 如果需要列名,先给矩阵添加列名再提取
colnames(m3) <- paste0("col", 1:ncol(m3)) # 自定义列名示例
row_ones_names <- apply(m3, 1, function(x) colnames(m3)[which(x == 1)])

解释:apply(m3, 1, ...)表示按行遍历矩阵(第二个参数1代表行),which(x == 1)会返回当前行中值为1的元素的位置索引;如果矩阵有列名,直接用colnames(m3)[which(x == 1)]就能拿到对应的列名。最终返回的是一个列表,每个元素对应一行的结果,完全适配每行1数量不同的情况。

方法2:用tidyverse工具(适合数据框工作流)

如果你习惯用tidyverse的风格处理数据,可以把矩阵转成长格式数据框后再筛选分组:

library(tidyverse)

set.seed(444)
m3 <- matrix(round(runif(8*8)), 8,8) %>%
  as.data.frame() %>%
  mutate(row_id = row_number()) # 添加行号用于分组

# 提取列索引
row_ones_indices_tidy <- m3 %>%
  pivot_longer(-row_id, names_to = "col_name", values_to = "value") %>%
  filter(value == 1) %>%
  group_by(row_id) %>%
  summarise(col_indices = list(as.integer(str_remove(col_name, "V")))) # 提取默认列名中的数字

# 提取自定义列名的情况
colnames(m3) <- paste0("col", 1:ncol(m3))
row_ones_names_tidy <- m3 %>%
  pivot_longer(-row_id, names_to = "col_name", values_to = "value") %>%
  filter(value == 1) %>%
  group_by(row_id) %>%
  summarise(col_names = list(col_name))

解释:先把矩阵转成数据框并添加行号,再用pivot_longer把宽格式转成长格式,筛选出值为1的行后按行号分组汇总,把每行的列索引/列名存成列表,结果清晰易读。

方法3:向量化操作(适合大型矩阵,效率更高)

如果你的矩阵规模很大,这种向量化方法比逐行循环更高效:

set.seed(444)
m3 <- matrix(round(runif(8*8)), 8,8)

# 获取所有1的行列位置矩阵
ones_pos <- which(m3 == 1, arr.ind = TRUE)

# 按行号分组,提取列索引
row_ones_indices_vec <- split(ones_pos[, "col"], ones_pos[, "row"])

# 提取列名的情况
colnames(m3) <- paste0("col", 1:ncol(m3))
row_ones_names_vec <- split(colnames(m3)[ones_pos[, "col"]], ones_pos[, "row"])

解释:which(m3 == 1, arr.ind = TRUE)会直接返回所有值为1的元素的行列位置矩阵,接着用split按行号分组,把对应的列索引/列名拆分到每个行的列表元素中,这种方法避免了逐行循环,处理大型矩阵时速度更快。

你可以根据自己的习惯和矩阵规模选择合适的方法,比如你提到的示例中第一行的2、3、8列是1,运行代码后row_ones_indices[[1]]会返回c(2, 3, 8),完全符合预期~

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

火山引擎 最新活动