如何基于多个条件语句创建多个新列?

时间:2019-04-05 22:15:52

标签: r conditional

[第一个堆栈问题,请:)友善!

我正在基于现有列的多个条件语句-实质上是所有新的列组合来在数据框中创建多个新列。

例如,如果有4列(a:d),则需要所有组合(abcd,abc,abd等)的新列,并基于a:d中的阈值数据进行0/1编码。

包括玩具数据示例和所需结果。但是需要可伸缩:有4个基本列,但我需要2、3和4列的所有组合,而不仅仅是3值(abc,abd,...。ab,ac,ad,...总计n = 11)

[背景资料:这实际上是来自多能干细胞的流式细胞仪数据,可以成长为所有谱系细胞类型(多能或abcd)的集落或受限制人群(仅abc) ,或abdabac等)

# Toy data set
set.seed(123)
df <- tibble(a = c(sample(10:50, 10)),
             b = c(sample(10:50, 10)),
             c = c(sample(10:50, 10)),
             d = c(sample(10:50, 10)))

当前代码会产生理想的结果,但是,这需要11行重复代码,容易出错,我希望有一个更优雅的解决方案:

df %>% 
  mutate(
    abcd = if_else(a > 30 & b > 20 & c > 30 & d > 30, 1, 0),
    abc = if_else(a > 30 & b > 20 & c > 30 & d <= 30, 1, 0),
    abd = if_else(a > 30 & b > 20 & c <= 30 & d > 30, 1, 0),
    acd = if_else(a > 30 & b <= 20 & c > 30 & d > 30, 1, 0),
    bcd = if_else(a <= 30 & b > 20 & c > 30 & d > 30, 1, 0))

2 个答案:

答案 0 :(得分:2)

我从您的问题中了解到,对于每一行,您只需要查找符合您ifelse()条件中定义的条件的列即可。此矢量化解决方案将在您的df中添加一列,其中包含所有组合。这也可能比多个ifelse条件还要快。最后,新列可用于排序或分组。

# define the threshold levels for all columns
threshold = c(a=30, b=20, c=30, d=30)

# get names of columns meeting the threshold and paste names
df$combn <- apply(df, 1, function(x) {
  paste(names(x)[x > threshold], collapse = "")
})

> df
# A tibble: 10 x 5
       a     b     c     d combn
   <int> <int> <int> <int> <chr>
 1    21    49    46    49 bcd  
 2    41    28    37    46 abcd 
 3    25    36    34    36 bcd  
 4    43    31    47    40 abcd 
 5    44    13    48    10 ac   
 6    11    42    35    27 bc   
 7    28    18    29    48 d    
 8    40    11    30    17 a    
 9    46    20    19    20 a    
10    24    40    14    43 bd   

答案 1 :(得分:0)

如果我正确地理解了这一点,那么您希望将每一行准确地归为一个类,因此获取类别名称作为阈值测试的串联应该足够了。然后,您可以使用0/1获得spread()列:

df %>% 
  mutate(
    a_ = if_else(a > 30, 'a', 'x'),
    b_ = if_else(b > 20, 'b', 'x'),
    c_ = if_else(c > 30, 'c', 'x'),
    d_ = if_else(d > 30, 'd', 'x'),
    all_ = paste0(a_, b_, c_, d_),
    one_ = 1) %>% 
  spread(all_, one_, fill = 0) %>% 
  select(-ends_with("_"))

给予

# A tibble: 10 x 11
       a     b     c     d  abcd  axcx  axxx  xbcd  xbcx  xbxd  xxxd
   <int> <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1    11    42    35    27     0     0     0     0     1     0     0
 2    21    49    46    49     0     0     0     1     0     0     0
 3    24    40    14    43     0     0     0     0     0     1     0
 4    25    36    34    36     0     0     0     1     0     0     0
 5    28    18    29    48     0     0     0     0     0     0     1
 6    40    11    30    17     0     0     1     0     0     0     0
 7    41    28    37    46     1     0     0     0     0     0     0
 8    43    31    47    40     1     0     0     0     0     0     0
 9    44    13    48    10     0     1     0     0     0     0     0
10    46    20    19    20     0     0     1     0     0     0     0

(您可以使用''代替'x',但是spread()会覆盖您的某些原始列。)