对数据框内的两组列应用条件

时间:2019-06-04 02:40:07

标签: r

我有一个df:

    Sub Remove_Empties ()

    Dim Last as Long
    Dim Mcol as Range

    Last = Cells(Rows.Count, "AD").End(xlUp).Row
    If Last = 1 Then Exit Sub 'no value only header in row 1
    'otherwise
    Set Mcol = Range("AD2:AD" & Last) 'contains any value
    Application.ScreenUpdating = True
    Mcol.SpecialCells(xlCellTypeBlanks).Delete xlUp
    Application.ScreenUpdating = True

    End Sub

我在列中有两组样本,例如'pre'和post':

    1         2         3
    A       
    B  
    C         A
    D         B
              C
              D

我想应用一个条件,即通过前100%和通过后50%或通过50%之前和通过后100%

例如

如果“ pre”的100%为3或以上,而50%的post为3或以上,则保留行  要么 如果“ pre”的50%为3或以上,而100%post为3或以上,则保留行 因此在示例df中,只有行“ a”会保留

我有:

a<-c(5,1,5,3,5,3,5,1)
b<-c(1,5,1,5,1,5,3,5)

df<-as.data.frame(rbind(a,b))
names(df)<-c('pre1','post1','pre2','post2','pre3','post3','pre4','post4')

但是我得到了一个“ TRUE”向量,这不是我想要的。

4 个答案:

答案 0 :(得分:2)

我们可以创建一个逻辑向量以使用rowSums

进行比较
df[(rowSums(df[pre] >= 3)/length(pre) == 1) & 
    (rowSums(df[post] >= 3)/length(post) >= 0.5) |
    (rowSums(df[post] >= 3)/length(post) == 1) & 
    (rowSums(df[pre] >= 3)/length(pre) >= 0.5), ]

#  pre1 post1 pre2 post2 pre3 post3 pre4 post4
#a    5     1    5     3    5     3    5     1

使用apply我们可以做到

df[apply(df[pre] >= 3, 1, all) & apply(df[post] >= 3, 1, sum)/length(post) >= 0.5 |
   apply(df[post] >= 3, 1, all) & apply(df[pre] >= 3, 1, sum)/length(pre) >= 0.5, ]

答案 1 :(得分:2)

这是一个不太简洁的tidyverse解决方案,可能会大大缩短。

library(data.table)
as.data.table(mtcars)[order(factor(cyl, levels = c(4, 8, 6)))]

答案 2 :(得分:0)

这是tidyverse

的一个选项
library(tidyverse)
library(rap)
crossing(val = c(0.5, 1), cols = c("pre", "post")) %>%
   rap(x = ~ df %>% 
                 select(matches(cols)) %>%
                 {rowMeans(. >=3) >= val}) %>%
                 group_by(val) %>% 
                 transmute(ind = reduce(x, `&`)) %>% 
                 filter(any(ind)) %>% 
                 pull(ind) %>% 
   filter(df, .)
#  pre1 post1 pre2 post2 pre3 post3 pre4 post4
#1    5     1    5     3    5     3    5     1

答案 3 :(得分:0)

这是一个基本的R解决方案,它按行名拆分,使用sapply检查条件,并将输出用作df上的逻辑索引:

df[sapply(split(df, rownames(df)), function(x) {
    (sum(x[pre] > 2)/ncol(x[pre]) >= .5) & (sum(x[post] > 2)/ncol(x[post]) == 1) ||
    (sum(x[pre] > 2)/ncol(x[pre]) == 1) & (sum(x[post] > 2)/ncol(x[post]) >= .5)
}),]

#### OUTPUT ####

  pre1 post1 pre2 post2 pre3 post3 pre4 post4
a    5     1    5     3    5     3    5     1