根据所有组中值的长度过滤 data.frame 中的行
Filter rows in data.frame based on the length of values in all groups
我有一个 data.frame 这样的:
df<-data.frame( Id = paste0("g",1:6),
a= c(6:11),
b = c(10:13,NA,NA),
c = c(7:10,NA,10),
d = c(NA,7:9,NA,13),
e= c(NA,6:10),
f= c(NA,NA,NA,4:5,NA))
colnames(df)=c("ID",rep("normal",3),rep("patient",3))
> df
ID normal normal normal patient patient patient
1 g1 6 10 7 NA NA NA
2 g2 7 11 8 7 6 NA
3 g3 8 12 9 8 7 NA
4 g4 9 13 10 9 8 4
5 g5 10 NA NA NA 9 5
6 g6 11 NA 10 13 10 NA
这个 df 包含两组(正常和患者)的数据。我要对所有行进行一些分析,因此每行中的所有组必须至少有两个 values.I 使用以下代码来过滤所有组都没有至少两个值的行。
fx=function(x){length(x[!is.na(x)])>=2}
f1=apply(df[,2:4], 1,fx)#filter based on group normal
f2=apply(df[,5:7], 1,fx)#filter based on group patient
df=subset(df,f1&f2)
> df
ID normal normal.1 normal.2 patient patient.1 patient.2
2 g2 7 11 8 7 6 NA
3 g3 8 12 9 8 7 NA
4 g4 9 13 10 9 8 4
6 g6 11 NA 10 13 10 NA
但是这些代码对于组数有限的数据很有用。我的主要数据有 100 个组(所有组都有 3 个重复),colnames(df)=paste0("grp",sort(rep(1:100,3)))
因此我需要一些简单的代码来过滤 data.frame 中有 100 个组的行。
我的目标:删除每组中没有至少两个值的行。
可以做到:
library(dplyr)
names(df) <- paste0(names(df), 1:ncol(df))
df %>%
filter(
rowSums(!is.na(select(., contains("normal")))) >= 2 &
rowSums(!is.na(select(., contains("patient")))) >= 2
)
我们可以使用 rowSums
区分 "normal"
和 "patient"
列以及 select 行
normal_cols <- grep("normal", names(df))
patient_cols <- grep("patient", names(df))
df[rowSums(!is.na(df[normal_cols])) >= 2 & rowSums(!is.na(df[patient_cols])) >= 2,]
# ID normal normal normal patient patient patient
#2 g2 7 11 8 7 6 NA
#3 g3 8 12 9 8 7 NA
#4 g4 9 13 10 9 8 4
#6 g6 11 NA 10 13 10 NA
或者使用您定义的 fx
函数,我们可以在两组列上使用 apply
两次,在行上使用 subset
.[=18= select ]
fx = function(x) {length(x[!is.na(x)])>=2}
subset(df, apply(df[normal_cols], 1,fx) & apply(df[patient_cols], 1,fx))
我们可以用reshape
得到一个长格式,看看colSums
.
此类问题的首要规则是 appRopriate 列名称,即 <chr_prefix>.<num_suffix>
.
names(df) <- c("ID", paste(rep(c("normal", "patient"), each=3), 1:3, sep="."))
现在我们reshape
成长格式并拆分by
"ID"
。我们只想要 all
colSums
为 > 2
的那些 ID,我们将其存储在一个向量 s
中,我们可以使用该向量对数据帧 df
.
r <- reshape(df, idvar="ID", direction="long", varying=list(2:4, 5:7), times=1:3)
s <- by(r[-1], r$ID, function(i) all(colSums(i, na.rm=TRUE) > 2))
df[s, ]
# ID normal normal normal patient patient patient
# 2 g2 7 11 8 7 6 NA
# 3 g3 8 12 9 8 7 NA
# 4 g4 9 13 10 9 8 4
# 6 g6 11 NA 10 13 10 NA
数据
df <- structure(list(Id = structure(1:6, .Label = c("g1", "g2", "g3",
"g4", "g5", "g6"), class = "factor"), a = 6:11, b = c(10L, 11L,
12L, 13L, NA, NA), c = c(7, 8, 9, 10, NA, 10), d = c(NA, 7, 8,
9, NA, 13), e = c(NA, 6L, 7L, 8L, 9L, 10L), f = c(NA, NA, NA,
4L, 5L, NA)), class = "data.frame", row.names = c(NA, -6L))
我有一个 data.frame 这样的:
df<-data.frame( Id = paste0("g",1:6),
a= c(6:11),
b = c(10:13,NA,NA),
c = c(7:10,NA,10),
d = c(NA,7:9,NA,13),
e= c(NA,6:10),
f= c(NA,NA,NA,4:5,NA))
colnames(df)=c("ID",rep("normal",3),rep("patient",3))
> df
ID normal normal normal patient patient patient
1 g1 6 10 7 NA NA NA
2 g2 7 11 8 7 6 NA
3 g3 8 12 9 8 7 NA
4 g4 9 13 10 9 8 4
5 g5 10 NA NA NA 9 5
6 g6 11 NA 10 13 10 NA
这个 df 包含两组(正常和患者)的数据。我要对所有行进行一些分析,因此每行中的所有组必须至少有两个 values.I 使用以下代码来过滤所有组都没有至少两个值的行。
fx=function(x){length(x[!is.na(x)])>=2}
f1=apply(df[,2:4], 1,fx)#filter based on group normal
f2=apply(df[,5:7], 1,fx)#filter based on group patient
df=subset(df,f1&f2)
> df
ID normal normal.1 normal.2 patient patient.1 patient.2
2 g2 7 11 8 7 6 NA
3 g3 8 12 9 8 7 NA
4 g4 9 13 10 9 8 4
6 g6 11 NA 10 13 10 NA
但是这些代码对于组数有限的数据很有用。我的主要数据有 100 个组(所有组都有 3 个重复),colnames(df)=paste0("grp",sort(rep(1:100,3)))
因此我需要一些简单的代码来过滤 data.frame 中有 100 个组的行。
我的目标:删除每组中没有至少两个值的行。
可以做到:
library(dplyr)
names(df) <- paste0(names(df), 1:ncol(df))
df %>%
filter(
rowSums(!is.na(select(., contains("normal")))) >= 2 &
rowSums(!is.na(select(., contains("patient")))) >= 2
)
我们可以使用 rowSums
"normal"
和 "patient"
列以及 select 行
normal_cols <- grep("normal", names(df))
patient_cols <- grep("patient", names(df))
df[rowSums(!is.na(df[normal_cols])) >= 2 & rowSums(!is.na(df[patient_cols])) >= 2,]
# ID normal normal normal patient patient patient
#2 g2 7 11 8 7 6 NA
#3 g3 8 12 9 8 7 NA
#4 g4 9 13 10 9 8 4
#6 g6 11 NA 10 13 10 NA
或者使用您定义的 fx
函数,我们可以在两组列上使用 apply
两次,在行上使用 subset
.[=18= select ]
fx = function(x) {length(x[!is.na(x)])>=2}
subset(df, apply(df[normal_cols], 1,fx) & apply(df[patient_cols], 1,fx))
我们可以用reshape
得到一个长格式,看看colSums
.
此类问题的首要规则是 appRopriate 列名称,即 <chr_prefix>.<num_suffix>
.
names(df) <- c("ID", paste(rep(c("normal", "patient"), each=3), 1:3, sep="."))
现在我们reshape
成长格式并拆分by
"ID"
。我们只想要 all
colSums
为 > 2
的那些 ID,我们将其存储在一个向量 s
中,我们可以使用该向量对数据帧 df
.
r <- reshape(df, idvar="ID", direction="long", varying=list(2:4, 5:7), times=1:3)
s <- by(r[-1], r$ID, function(i) all(colSums(i, na.rm=TRUE) > 2))
df[s, ]
# ID normal normal normal patient patient patient
# 2 g2 7 11 8 7 6 NA
# 3 g3 8 12 9 8 7 NA
# 4 g4 9 13 10 9 8 4
# 6 g6 11 NA 10 13 10 NA
数据
df <- structure(list(Id = structure(1:6, .Label = c("g1", "g2", "g3",
"g4", "g5", "g6"), class = "factor"), a = 6:11, b = c(10L, 11L,
12L, 13L, NA, NA), c = c(7, 8, 9, 10, NA, 10), d = c(NA, 7, 8,
9, NA, 13), e = c(NA, 6L, 7L, 8L, 9L, 10L), f = c(NA, NA, NA,
4L, 5L, NA)), class = "data.frame", row.names = c(NA, -6L))