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

时间:2016-04-12 02:04:38

标签: r dataframe subset

我想对data.frame进行子集化,以便它只返回至少有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。 我只想返回行r3,因为75%的值都是<=r1中的值。

df

Name   A   B   C   D
r3     1   1   1   2

任何帮助将不胜感激。如果需要进一步的信息,请告诉我。

2 个答案:

答案 0 :(得分:2)

使用&#34; +&#34;逐行添加满足的条件数。并与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

如果你想删除&#39; r1&#39;然后只需附加[-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,因为`apply以列为导向的方式返回矩阵,有时候是一个难题来开始。

答案 1 :(得分:0)

以下是通用解决方案,也可以应用于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包来提高效果。