[第一个堆栈问题,请:)
友善!
我正在基于现有列的多个条件语句-实质上是所有新的列组合来在数据框中创建多个新列。
例如,如果有4列(a:d),则需要所有组合(abcd,abc,abd等)的新列,并基于a:d中的阈值数据进行0/1编码。
包括玩具数据示例和所需结果。但是需要可伸缩:有4个基本列,但我需要2、3和4列的所有组合,而不仅仅是3值(abc,abd,...。ab,ac,ad,...总计n = 11)
[背景资料:这实际上是来自多能干细胞的流式细胞仪数据,可以成长为所有谱系细胞类型(多能或abcd
)的集落或受限制人群(仅abc
) ,或abd
,ab
,ac
等)
# 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))
答案 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()
会覆盖您的某些原始列。)