У меня есть набор данных, в котором многие переменные на самом деле являются своего рода «горячим кодированием», и я хотел бы свернуть его, чтобы иметь одну переменную со значением.
name born_2017 born_2018 born_2019
<chr> <dbl> <dbl> <dbl>
1 Paul 0 1 0
2 Diane 0 0 1
3 Jose 1 0 0
И я хочу, чтобы это выглядело так:
name birth_year
<chr> <chr>
1 Paul born_2018
2 Diane born_2019
3 Jose born_2017
Облазил dplyr
и tidyr
но как-то не нашел то что нужно.
ps: мне нужно сделать это для многих переменных, поэтому легко обобщаемое решение или работа с каналом было бы очень полезно
@NelsonGon Это не та же проблема, я не хочу, чтобы в конце было больше строк.
Как сейчас написано, это та же проблема. Что происходит с 0 и 1?!
Вы можете использовать gather
library(dplyr)
df %>%
gather(birth_year ,flag , born_2017:born_2018) %>%
filter(flag == 1) %>%
select(-flag)
Я думал об этом, но тот факт, что я должен использовать флаг, добавляя много строк в код, так как я должен делать это для многих переменных, довольно скучен.
example <- read.table(text = "
name born_2017 born_2018 born_2019
Paul 0 1 0
Diane 0 0 1
Jose 1 0 0", h = T)
В этом конкретном примере это может работать только с базой R:
example$birth_year <- colnames(example[,2:4])[apply(example[,2:4], 1, which.max)]
example[,c("name", "birth_year")]
name birth_year
1 Paul born_2018
2 Diane born_2019
3 Jose born_2017
Основываясь на предложениях Сотоса, следующие два подхода векторизованы, не нуждаются в apply
и являются более плотными, и поэтому предпочтительнее:
subset(cbind(example[1], stack(example[-1])), values == 1)
или
names(example[-1])[max.col(example[-1])]
Есть векторизованные способы сделать это через базу R, которые не требуют apply
. Например, subset(cbind(df[1], stack(df[-1])), values == 1)
или следуя своей мысли, просто names(df[-1])[max.col(df[-1])]
Это даже лучше, большое спасибо :) Надеюсь, вы не возражаете, что я обновил свой ответ.
Что происходит с «кодировкой». Его просто выбрасывают?