#r #tidyverse
Вопрос:
У меня есть два набора данных разной длины. Я хочу создать новый столбец в наборе данных, в котором будет больше строк, на основе фильтрации определенного столбца из более короткого df. Я получаю предупреждение «Более длинная длина объекта не кратна более короткой длине объекта». И результат тоже не верен. Я попытался создать меньшие примеры наборов данных и попробовал тот же код и его работу с правильными результатами. Я не уверен, почему на моих исходных данных результаты неверны, и я получаю предупреждение. Примерами наборов данных являются
structure(list(id = 1:10, activity = c(0, 0, 0, 0, 1, 0, 0, 1,
0, 0), code = c(2, 5, 11, 15, 3, 18, 21, 3, 27, 55)), class = "data.frame", row.names = c(NA,
-10L))
второй df
structure(list(id2 = 1:20, code2 = c(2, 5, 11, 15, 9, 18, 21,
3, 27, 55, 2, 5, 11, 15, 3, 18, 21, 3, 27, 55), d_Activity = c(0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0)), class = "data.frame", row.names = c(NA,
-20L))
Я попробовал это как на своих исходных наборах данных, где я получаю предупреждение, так и на этих фиктивных dfs, где нет предупреждения и правильных результатов.
data2 <- data2 %>%
mutate(d_Activity = ifelse(code2 %in% data1$code amp; activity == 1, 1,0))
Ответ №1:
На самом деле, вы делаете это неправильно. Позвольте мне объяснить-
- В образцах данных это работает, потому что в больших df есть строки (20), которые кратны строкам в меньших df (10).
- Таким образом, в вашем синтаксисе вы делаете то, что проверяете один полный вектор другим полным вектором (столбцом другого df), потому что R обычно работает в векторизованном способе операций.
- правильный способ сопоставления
one to many
заключается вpurrr::map
том, что каждое отдельное значение в первом аргументе (код 2 здесь) работает с другим вектором, т. е.df1$code
Которого нет в аргументеmap
.
df1 <- structure(list(id = 1:10, activity = c(0, 0, 0, 0, 1, 0, 0, 1,
0, 0), code = c(2, 5, 11, 15, 3, 18, 21, 3, 27, 55)), class = "data.frame", row.names = c(NA,
-10L))
df2 <- structure(list(id2 = 1:20, code2 = c(2, 5, 11, 15, 9, 18, 21,
3, 27, 55, 2, 5, 11, 15, 3, 18, 21, 3, 27, 55), d_Activity = c(0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0)), class = "data.frame", row.names = c(NA,
-20L))
library(tidyverse)
df2 %>%
mutate(d_Activity = map(code2, ~ (.x %in% df1$code[df1$activity == 1])))
#> id2 code2 d_Activity
#> 1 1 2 0
#> 2 2 5 0
#> 3 3 11 0
#> 4 4 15 0
#> 5 5 9 0
#> 6 6 18 0
#> 7 7 21 0
#> 8 8 3 1
#> 9 9 27 0
#> 10 10 55 0
#> 11 11 2 0
#> 12 12 5 0
#> 13 13 11 0
#> 14 14 15 0
#> 15 15 3 1
#> 16 16 18 0
#> 17 17 21 0
#> 18 18 3 1
#> 19 19 27 0
#> 20 20 55 0
Создано 2021-06-17 пакетом reprex (v2.0.0)
Комментарии:
1. Не совсем. Мне нужен код 2 из df2, который присутствует в коде df1$, а также где столбец активности в df1 ==1 также.
2. если вы посмотрите на строку кода, которую я включил в вопрос с помощью mutate и ifelse, это прекрасно работает, но не мой исходный набор данных, которым я не могу поделиться.
3. Я думаю, что это сработало с моим исходным набором данных, и результаты кажутся хорошими. Я был бы признателен за некоторое объяснение синтаксиса кода. Овации
4. @камранхан, я пытался объяснить эти вещи. Не стесняйтесь спрашивать, нужно ли разъяснение.