如何在 R 中的同一 data.frame 中按行对 data.frame 进行子集化?

How to subset a data.frame by a row in the same data.frame in R?

我想对我的 data.frame 进行子集化,以便它仅 return 具有至少 50% 值的行 <= 中特定行中的值data.frame.

df

Name   A   B   C   D
r1     2   2   2   2
r2     4   3   1   3
r3     1   1   1   2
r4     3   3   3   1

我尝试子集化的特定行是行 r1。 我只想 return 行 r3 因为 75% 的值是 <=r1.

中的值

df

Name   A   B   C   D
r3     1   1   1   2

如有任何帮助,我们将不胜感激。如果需要更多信息,请告诉我。

使用“+”将满足的条件数逐行相加并与 3 进行比较:

subset(df, ( (A <= A[1]) + (B <= B[1]) + (C <= C[1]) + (D <= D[1]) ) >= 3 )

> subset(df, ( (A <= A[1]) + (B <= B[1]) + (C <= C[1]) + (D <= D[1]) ) >= 3 )
  Name A B C D
1   r1 2 2 2 2
3   r3 1 1 1 2

如果您还想删除 'r1' 那么只需附加 [-1, ]

这可以概括为提供一个可以根据百分比标准进行测试的数字向量;它给出每行中少于第一行对应项的项目数。我需要 unlist 第一行,因为使用第三个参数作为单行数据帧失败:

rowSums(sweep(df[-1], 2, unlist(df[1,-1]), "<="))
[1] 4 2 4 2

下面是演示:

df2 <- cbind(nms = paste0("r", 1:10), 
             as.data.frame( matrix(sample( 1:10, 200,repl=TRUE), 10) ) )
df2
#--------------
nms V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20
1   r1  8  6 10  7  3  7  2  8  4   9   9   4   5   4   8   7   2   1   6   4
2   r2  3  9  6  3  9 10  6 10 10   3   3   2   4   4   4  10   3   5   2   1
3   r3  1  7  6  8  3  5  2  3  1   5   5   4   8   3   1   6   2  10   3   7
4   r4  2  6 10 10  8  7  9  1  4   5   6   7   2   6   8   3   5  10  10   3
5   r5  5  5  7  2  5 10  2  9  2   9   4   6   1   5   8   5   8   6   3   5
6   r6  4  1  7  7  6  9  6  3  4   3   2   9   4   8  10   3   4   4  10   4
7   r7  7  1 10  4  1  2  8  5  8   8   5   5   5   6   4  10   6   9  10   6
8   r8 10  8  1  4  1  4 10  3  1   3  10   3   4   9   4   7   4   9   2   2
9   r9  3 10  9  1 10  8  8  4  7   2   7   2   9  10   3   3   7   4  10   1
10 r10  4  7  3  3  1  9  4  1  9   5   3   9   9   3   9   2   9  10   2   4
#-----------------
rowSums(sweep(df2[-1], 2, unlist(df2[1,-1]), "<="))
# [1] 20 11 15 12 12 11 11 13 10 11
rowSums(sweep(df2[-1], 2, unlist(df2[1,-1]), "<=")) >= 20*0.75
# [1]  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

 df2[ rowSums(sweep(df2[-1], 2, unlist(df2[1,-1]), "<=")) >= 20*0.75 , ]
#---------
  nms V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20
1  r1  8  6 10  7  3  7  2  8  4   9   9   4   5   4   8   7   2   1   6   4
3  r3  1  7  6  8  3  5  2  3  1   5   5   4   8   3   1   6   2  10   3   7

我想到 apply 解决方案对于一些 R 程序员来说可能更明显:

 colSums( apply(df2[-1], 1, "<=", df2[1,-1]) ) >= ncol(df2)*.7

请注意需要使用 colSums,因为它以面向列的方式`应用returns 矩阵,有时对初学者来说是个难题。

下面是通用的解决方案,也可以应用于 34 个变量:

假设:在数据集中,我们正在比较除存储 Name.

的第一列之外的每一列
> col_names <- colnames(df)[-1]

> index <- which(df$Name == 'r1')
> values <- seq(1:nrow(df))[-index]

> row_num <- integer(0)
> for (i in values){
+ min_val <- length(col_names) / 2
+ if (length(which(df[i,col_names] <= df[index,col_names])) >= min_val)
+ row_num <- c(row_num,i)
+ }

> df[row_num,]
  Name A B C D
3   r3 1 1 1 2

虽然如果数据集很大,可能需要一些时间。您可以在 data.table 包的帮助下提高性能。