R:对于具有部分字符串匹配的一组列名,每行查找列数 > 0
R: find number of columns > 0 per row for a group of column names with a partial string match
我有一个类似于以下内容的数据框:
ID
X
Y
A_1_l
A_2_m
B_1_n
B_2_l
C_1_m
C_2_n
C_3_l
w
X
Y
0
0
0
0
0
0
0
x
X
Y
0
0
3
0
0
0
0
y
X
Y
0
1
0
4
0
1
0
z
X
Y
3
4
5
6
2
1
5
第一个字母表示样本,数字表示重复,第二个字母表示批次。我正在尝试计算每个 ID 至少有一个值 > 0 的样本数量,并将这些数字存储在列表中。
这是我可以附加到现有数据框的列表的期望结果:
0,1,3,3
对于之前的分析,我使用 strsplit
来计算每批样本的总数。
colsList <- colnames(df)
cols <- grep("_", colsList, value=TRUE)
splitList <- strsplit(cols, "_\d_")
stats <-data.frame(t(as.data.frame.list(splitList)))
rownames(stats)<-NULL
names(stats)<-c("Sample", "Batch")
perSample <- aggregate(Sample ~ Batch, stats,
function(x) length(unique(x))) # number of strains
而且我能够使用 rowSums(df[sapply(df, is.numeric)] > 0)
找到值 > 0 的列总数,但我似乎无法弄清楚如何将两者结合起来找到样本总数 > 0
首先过滤数据以仅保留数字列。
使用 split.default
将数据分组,这样所有 'A'
列都在一组中,'B'
列在另一组中,依此类推。在每个组中 return TRUE
如果一行有一个大于 0 的值,sum
将所有组中的所有值加在一起以获得最终计数。
tmp <- Filter(is.numeric, df)
rowSums(sapply(split.default(tmp, sub('_.*', '', names(tmp))),
function(x) rowSums(x) > 0))
#[1] 0 1 3 3
我们可以在 tidyverse
library(dplyr)
library(stringr)
library(tidyr)
df1 %>%
select(ID, where(is.numeric)) %>%
pivot_longer(cols = -ID) %>%
mutate(name = str_remove(name, "_.*")) %>%
group_by(ID, name) %>%
summarise(value = sum(value > 0), .groups = 'drop_last') %>%
summarise(value = sum(value > 0))
# A tibble: 4 x 2
ID value
<chr> <int>
1 w 0
2 x 1
3 y 3
4 z 3
数据
df1 <- structure(list(ID = c("w", "x", "y", "z"), X = c("X", "X", "X",
"X"), Y = c("Y", "Y", "Y", "Y"), A_1_l = c(0L, 0L, 0L, 3L), A_2_m = c(0L,
0L, 1L, 4L), B_1_n = c(0L, 3L, 0L, 5L), B_2_l = c(0L, 0L, 4L,
6L), C_1_m = c(0L, 0L, 0L, 2L), C_2_n = c(0L, 0L, 1L, 1L), C_3_l = c(0L,
0L, 0L, 5L)), class = "data.frame", row.names = c(NA, -4L))
我有一个类似于以下内容的数据框:
ID | X | Y | A_1_l | A_2_m | B_1_n | B_2_l | C_1_m | C_2_n | C_3_l |
---|---|---|---|---|---|---|---|---|---|
w | X | Y | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
x | X | Y | 0 | 0 | 3 | 0 | 0 | 0 | 0 |
y | X | Y | 0 | 1 | 0 | 4 | 0 | 1 | 0 |
z | X | Y | 3 | 4 | 5 | 6 | 2 | 1 | 5 |
第一个字母表示样本,数字表示重复,第二个字母表示批次。我正在尝试计算每个 ID 至少有一个值 > 0 的样本数量,并将这些数字存储在列表中。
这是我可以附加到现有数据框的列表的期望结果:
0,1,3,3
对于之前的分析,我使用 strsplit
来计算每批样本的总数。
colsList <- colnames(df)
cols <- grep("_", colsList, value=TRUE)
splitList <- strsplit(cols, "_\d_")
stats <-data.frame(t(as.data.frame.list(splitList)))
rownames(stats)<-NULL
names(stats)<-c("Sample", "Batch")
perSample <- aggregate(Sample ~ Batch, stats,
function(x) length(unique(x))) # number of strains
而且我能够使用 rowSums(df[sapply(df, is.numeric)] > 0)
找到值 > 0 的列总数,但我似乎无法弄清楚如何将两者结合起来找到样本总数 > 0
首先过滤数据以仅保留数字列。
使用 split.default
将数据分组,这样所有 'A'
列都在一组中,'B'
列在另一组中,依此类推。在每个组中 return TRUE
如果一行有一个大于 0 的值,sum
将所有组中的所有值加在一起以获得最终计数。
tmp <- Filter(is.numeric, df)
rowSums(sapply(split.default(tmp, sub('_.*', '', names(tmp))),
function(x) rowSums(x) > 0))
#[1] 0 1 3 3
我们可以在 tidyverse
library(dplyr)
library(stringr)
library(tidyr)
df1 %>%
select(ID, where(is.numeric)) %>%
pivot_longer(cols = -ID) %>%
mutate(name = str_remove(name, "_.*")) %>%
group_by(ID, name) %>%
summarise(value = sum(value > 0), .groups = 'drop_last') %>%
summarise(value = sum(value > 0))
# A tibble: 4 x 2
ID value
<chr> <int>
1 w 0
2 x 1
3 y 3
4 z 3
数据
df1 <- structure(list(ID = c("w", "x", "y", "z"), X = c("X", "X", "X",
"X"), Y = c("Y", "Y", "Y", "Y"), A_1_l = c(0L, 0L, 0L, 3L), A_2_m = c(0L,
0L, 1L, 4L), B_1_n = c(0L, 3L, 0L, 5L), B_2_l = c(0L, 0L, 4L,
6L), C_1_m = c(0L, 0L, 0L, 2L), C_2_n = c(0L, 0L, 1L, 1L), C_3_l = c(0L,
0L, 0L, 5L)), class = "data.frame", row.names = c(NA, -4L))