Создание столбца на основе фильтрации двух фреймов данных разной длины с использованием R

#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. @камранхан, я пытался объяснить эти вещи. Не стесняйтесь спрашивать, нужно ли разъяснение.