将虚拟变量转换为 R 中的单个分类变量?

问题描述 投票:0回答:2

类似的问题已在此处此处此处提出。然而,它们似乎并没有完全满足我的需要。例如,如果我有一个像这样的数据集:

df <- data.frame(
  x = rnorm(10),
  y = rnorm(10),
  a = c(0,0,0,1,1,0,0,0,1,0),
  b = c(1,1,1,1,0,0,1,0,0,0),
  c = c(0,1,0,1,0,0,0,0,0,0),
  z = c(1,1,1,1,1,0,1,0,1,0)
)

我想做的是将变量

a
b
c
转换为单个类别,其中级别为
a
b
c
。但正如您所看到的,有时 2 个变量出现在同一行中。所以,我想要实现的是一个看起来像这样的数据框:

df <- data.frame(
  x = rnorm(10),
  y = rnorm(10),
  a = c(0,0,0,1,1,0,0,0,1,0),
  b = c(1,1,1,1,0,0,1,0,0,0),
  c = c(0,1,0,1,0,0,0,0,0,0),
  z = c(“b”,“b,c”,“b”,“a,b,c”,“a”,0,“b”,0,“a”,0)
)

我尝试使用:

apply(df[,c("a","b", "c")], 1, sum, na.rm=TRUE)

它对每个变量的数量进行求和...但我不确定如何将 2 个(或更多)变量组合成单个因子水平!?

关于我如何做到这一点有什么建议吗?

r
2个回答
5
投票

按行循环选定的列 (

MARGIN = 1
),对值为 1 的列名称进行子集化,并将它们
paste
放在一起

df$z <-  apply(df[c('a', 'b', 'c')], 1, function(x) toString(names(x)[x ==1]))
df$z
#[1] "b"       "b, c"    "b"       "a, b, c" "a"       ""        "b"       ""        "a"       ""       

如果我们想将

""
更改为“0”

df$z[df$z == ''] <- '0'

对于 purrr 和 dplyr 的解决方案:

df %>% mutate(z = pmap_chr(select(., a, b, c), ~  {v1 <- c(...); toString(names(v1)[v1 == 1])}))

0
投票

这是使用

pmap_chr
的另一种解决方案,类似于上面显示的 @akrun,但使用
across()
,然后用
NULL
值替换
0
单元格:

library(dplyr);library(purrr)
df |>
dplyr::mutate(z=pmap_chr(across(a:c), ~ paste(names(c(...)[c(...) > 0]), collapse = ","))) |>
mutate(across(z, ~ replace(.x, .x == '', "0")))

输出:

            x           y a b c     z
1  -0.3720247  1.09624218 0 1 0     b
2  -1.3545475  0.06103844 0 1 1   b,c
3   0.6472896 -1.15717339 0 1 0     b
4   0.2699036  0.82303370 1 1 1 a,b,c
5  -0.8318826  0.27290774 1 0 0     a
6  -0.7483059  0.79102464 0 0 0     0
7   1.1854403 -0.31954540 0 1 0     b
8   0.1317170 -0.52332482 0 0 0     0
9  -1.4327706 -0.45194686 1 0 0     a
10  0.3727059  1.85332187 0 0 0     0
© www.soinside.com 2019 - 2024. All rights reserved.