连接多对一:结合相关特征

kem*_*uan 5 r data-manipulation

我有一个数据框,其中每一行代表一个空间单元。nbid* 变量指示哪个单元是邻居。我想将邻居的虚拟变量放入主数据框中。(它可以不是空间单位,而是数据框架内的任何类型的关系 - 业务合作伙伴、亲戚、相关基因等。)一些简化的数据如下所示:

seed(999)
df_base <- data.frame(id = seq(1:100),
                 dum= sample(c(rep(0,50), rep(1,50)),100),
                 nbid_1=sample(1:100,100),
                 nbid_2=sample(1:100,100),
                 nbid_3=sample(1:100,100)) %>% 
  mutate(nbid_1 =  replace(nbid_1, sample(row_number(), size = ceiling(0.1 * n()), replace = FALSE), NA),
         nbid_2 =  replace(nbid_2, sample(row_number(), size = ceiling(0.3 * n()), replace = FALSE), NA),
         nbid_3 =  replace(nbid_3, sample(row_number(), size = ceiling(0.7 * n()), replace = FALSE), NA))
Run Code Online (Sandbox Code Playgroud)

(在这些简化数据中以及除了真实数据之外,邻居 1,2 和 3 可以相同,但这对于问题来说并不重要。)

我的方法是复制然后连接数据,如下所示:

df1 <- df_base
df2 <- df_base %>% 
  select(-c(nbid_1,nbid_2,nbid_3)) %>% 
  rename(nbdum=dum)

df <- left_join(df1,df2,by=c("nbid_1"="id")) %>% 
  rename(nbdum1=nbdum) %>% 
  left_join(.,df2,by=c("nbid_2"="id")) %>% 
  rename(nbdum2=nbdum) %>% 
  left_join(.,df2,by=c("nbid_3"="id")) %>% 
  rename(nbdum3=nbdum)

Run Code Online (Sandbox Code Playgroud)

df是我正在寻找的结果 - 从这里我可以创建一个整体邻居虚拟或计数。然而,对于具有更多邻居的真实数据来说,这种方法既不优雅也不可行。

我怎样才能以不那么笨拙的方式解决这个问题?

预先感谢您的想法!

Col*_*ole 2

一个关键线索是,当您看到 时var_1, var_2, ..., var_n,表明数据可以转换得更长。请参阅pivot_longer()或经常讨论数据的data.table::melt()地方。molten

\n

对于您的示例,我们可以先进行旋转,然后再将df2表连接回来。我不确定是否需要该格式,但在加入后,我们可以使用 转回宽格式pivot_wider()

\n
library(dplyr)\nlibrary(tidyr)\n\n\ndf1 %>%\n  select(!id) %>%\n  pivot_longer(cols = starts_with("nbid"), names_prefix = "nbid_")%>%\n  mutate(original_id = rep(1:100, each = 3))%>%\n  left_join(df2, by = c("value" = "id"))%>%\n  pivot_wider(original_id, values_from = c(value, nbdum))\n\n#> # A tibble: 100 \xc3\x97 7\n#>    original_id value_1 value_2 value_3 nbdum_1 nbdum_2 nbdum_3\n#>          <int>   <int>   <int>   <int>   <dbl>   <dbl>   <dbl>\n#>  1           1      25      90      23       0       0       1\n#>  2           2      12      NA      NA       1      NA      NA\n#>  3           3      11      40      47       0       0       0\n#>  4           4      94      87      NA       0       1      NA\n#>  5           5      46      77      NA       1       0      NA\n#>  6           6      98      82      NA       1       0      NA\n#>  7           7      43      NA      NA       1      NA      NA\n#>  8           8      74      NA       7       0      NA       1\n#>  9           9      57      NA      NA       1      NA      NA\n#> 10          10      49      72      NA       0       0      NA\n#> # \xe2\x80\xa6 with 90 more rows\n\n## compare to original\n\nas_tibble(df)\n#> # A tibble: 100 \xc3\x97 8\n#>       id   dum nbid_1 nbid_2 nbid_3 nbdum1 nbdum2 nbdum3\n#>    <int> <dbl>  <int>  <int>  <int>  <dbl>  <dbl>  <dbl>\n#>  1     1     0     25     90     23      0      0      1\n#>  2     2     1     12     NA     NA      1     NA     NA\n#>  3     3     1     11     40     47      0      0      0\n#>  4     4     1     94     87     NA      0      1     NA\n#>  5     5     0     46     77     NA      1      0     NA\n#>  6     6     1     98     82     NA      1      0     NA\n#>  7     7     1     43     NA     NA      1     NA     NA\n#>  8     8     0     74     NA      7      0     NA      1\n#>  9     9     0     57     NA     NA      1     NA     NA\n#> 10    10     0     49     72     NA      0      0     NA\n#> # \xe2\x80\xa6 with 90 more rows\n
Run Code Online (Sandbox Code Playgroud)\n