【问题标题】:How to create new columns based on pairwise combinations of all existing columns in R?如何基于 R 中所有现有列的成对组合创建新列?
【发布时间】:2020-09-07 00:11:17
【问题描述】:

我有一个包含约 6000 列的数据框。每列都包含一个国家名称,该名称代表图表中的一个节点。一行内的国家通过边连接。

看起来像这样:

df <- data.frame(ID = c(1,2,3), 
                  Country_1 = c("Germany", "Russia", "Germany"),
                  Country_2 = c(NA, "Germany", NA),
                  Country_n = c("China", "China", "China"))
ID Country_1 Country_2 ... Country_n 
1  Germany   NA        ... China     
2  Russia    Germany   ... China     
3  Germany   NA        ... China     
.
.
.

期望的结果

我想创建包含国家之间互动的新列。应该忽略 NA。

ID  Ctr_Int_1       Ctr_Int_2    ...   Ctr_Int_n 
1  Germany-China        NA       ...      NA
2  Russia-Germany   Russia-China ...  Germany-China   
3  Germany-China        NA       ...      NA  
.
.
.

代码

我可以逐步做到这一点[1],但 NA 不会被忽略,并且随着列数的增加,它不再可行了。

library(tidyr)
library(dplyr)

# step by step
df <- df %>% unite(CountryInt_1, Country_1, Country_2, sep = "-", remove = FALSE)
df <- df %>% unite(CountryInt_2, Country_1, Country_n, sep = "-", remove = FALSE)
df <- df %>% unite(CountryInt_3, Country_2, Country_n, sep = "-", remove = FALSE)

# remove additional columns
country_names <- paste0("Country_", 1:3)

`%ni%` <- Negate(`%in%`)
df <- subset(df,select = names(df) %ni% country_names)
ID  Ctr_Int_1       Ctr_Int_2     ...    Ctr_Int_n 
1  Germany-China    Germany-NA    ...    China-NA
2  Russia-Germany   Russia-China  ...    Germany-China   
3  Germany-NA       Germany-China ...    China-NA  
.
.
.

我认为这个问题或类似问题必须有解决方案,因为它不应该是闻所未闻的,但我无法找到它。我想应该有一种使用base::apply 和/或类似于这里[2 和这里3] 的方法 - 但我对data.table 不太熟悉并且无法实现它.

如果有人能指出我正确的方向,那肯定会有所帮助。

编辑:感谢@NotThatKindOdr,NAs 的问题得到了解决,但是,更紧迫的问题仍然存在,因为每次手动创建 Country-to-Country 组合是不可行的。

【问题讨论】:

  • 这些是你节点的边缘吗?
  • 抱歉回复晚了!是的,每个国家代表一个节点。这种组合代表了这些国家之间的单一互动。我没有详细说明背景,因为它可能会造成混淆而不是帮助。但是,创建国家/地区组合背后的想法是创建图表的选项,以捕获与另一个项目(如出版物所涉及的特定“研究领域”)的联系强度,就像我的例子一样。
  • 好的。但是当你说“节点”时,它让我想起了网络图。你熟悉 igraph 包吗?
  • 是的,我知道,但我并不像我想的那样熟悉。据我了解,它在网络分析方面提供了很多内容,但在之前必须发生的数据整理部分方面却较少……至少如果你有原始数据的话。

标签: r dataframe dplyr data.table tidyr


【解决方案1】:

它不会忽略 NA,但会将任何组合的 NA 替换为 NA 本身

df %>% mutate_all(~ifelse(str_detect(., "NA"), NA, .))

【讨论】:

  • 谢谢!这已经很有帮助了!对组合问题有何看法?
  • 为什么你在第三行第二列而不是第一列有德国 - 中国?老实说,我可能会pivot_longer 将所有交互放到同一列中,然后删除 NA。不过,这取决于您的用例。
  • 不,关于如何简化组合的创建。我有大约 6000 列,所以到目前为止我无法手动完成。
  • 我得考虑一下,今天晚些时候我会尽力给你一些东西
【解决方案2】:

使用data.table的选项:

library(data.table)
dcast(
    melt(setDT(df), id.vars="ID", na.rm=TRUE)[, 
        combn(value, 2L, function(x) paste(x, collapse="-")), ID][,
            ri := paste0("Ctr_Int_", rowid(ID))],
    ID ~ ri, value.var="V1")

输出:

   ID      Ctr_Int_1    Ctr_Int_2     Ctr_Int_3
1:  1  Germany-China         <NA>          <NA>
2:  2 Russia-Germany Russia-China Germany-China
3:  3  Germany-China         <NA>          <NA>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 2020-10-21
    • 2021-06-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多