合并列并在没有值

时间:2018-02-16 11:40:47

标签: r merge multiple-columns

我想从不同的数据帧合并19个不同长度的列并进行比较。这是一个例子:

df1: 
PA0001
PA0002
PA0003
PA0004
PA0005

df2: 
PA0001
PA0003
PA0006
PA0007


df3: 
PA0001
PA0007

等...

输出就是这样的:

PA0001  | PA0001 | PA0001
PA0002  |  NA    | NA
PA0003  | PA0003 | NA                   
PA0004  | NA     | NA
PA0005  | NA     | NA
NA      | PA0006 | NA
NA      | PA0007 | PA0007

我使用comparemerge功能,但我的效果不佳。我试图使用这个问题的功能:Link

但我收到了这个错误:

Error in attributes(.Data) <- c(attributes(.Data), attrib) : 
  'names' attribute [5254] must be the same length as the vector [2]

以下是您的例子:

test1 <- data.frame(c("PA0001","PA0002","PA0003","PA0004","PA0005","PA0006"))
test2 <- data.frame(c("PA0001","PA0002","PA0004","PA0005","PA0007"))
test3 <- data.frame(c("PA0001","PA0004","PA0005","PA0007", "PA0008"))

非常感谢你。

3 个答案:

答案 0 :(得分:6)

如果我们需要OP中预期的输出,请将数据集放在list中,然后在创建&#39; grp&#39;之前绑定list元素。列rbindlistdcast来自&#39; long&#39;广泛的&#39;通过match&#39; id&#39;在公式中创建序列列使用unique元素&#39; id&#39;

library(data.table)
dcast(rbindlist(list(test1, test2, test3), idcol = 'grp'),
         match(id, unique(id)) ~ paste0("col", grp))[, id := NULL][]
#     col1   col2   col3
#1: PA0001 PA0001 PA0001
#2: PA0002     NA     NA
#3: PA0003 PA0003     NA
#4: PA0004     NA     NA
#5: PA0005     NA     NA
#6:     NA PA0006     NA
#7:     NA PA0007 PA0007

或者@jogo分割代码,以便在第一步中rbind创建&#39; grp&#39;时list idcol中的所有数据集。列通过指定t_all <- rbindlist(list(test1, test2, test3), idcol='grp'); 参数

dcast

然后NULL,广泛&#39;格式并指定“id”#39;列到dcast(t_all, id ~ grp, value.var='id')[, id := NULL][]

test1 <- data.frame(id = c("PA0001","PA0002","PA0003","PA0004","PA0005"))
test2 <- data.frame(id = c("PA0001","PA0003","PA0006","PA0007"))
test3 <- data.frame(id = c("PA0001", "PA0007"))

数据

{% extends "music/base.html" %} 
{% block body %}    
    {% load staticfiles %}
    <img src="{% static 'music/image/Robot-PNG-File.png' %}" class="rounded-circle" alt="face" style='max-height:200px'><br>
    <h2>{{album.album_title}}</h2>
    <h3>{{album.artist}}</h3>
    <ul>
        {% for songs in album.song_set.all%}
            <li>{{songs.song_title}}- {{songs.file_type}}</li>
        {% endfor %}<br>
    </ul>
{% endblock %}

答案 1 :(得分:5)

您可以尝试tidyverse解决方案

library(tidyverse)
d1 <- read.table(text="PA0001
           PA0002
           PA0003
           PA0004
           PA0005")
d2 <- read.table(text="PA0001
           PA0003
           PA0006
           PA0007")
d3 <- read.table(text="PA0001
           PA0007")

list(d1, d2, d3) %>% 
  bind_rows(.id = "df") %>% 
  mutate(n = TRUE) %>% 
  spread(df, n, fill = FALSE)
      V1     1     2     3
1 PA0001  TRUE  TRUE  TRUE
2 PA0002  TRUE FALSE FALSE
3 PA0003  TRUE  TRUE FALSE
4 PA0004  TRUE FALSE FALSE
5 PA0005  TRUE FALSE FALSE
6 PA0006 FALSE  TRUE FALSE
7 PA0007 FALSE  TRUE  TRUE

我们的想法是将所有data.frame包含在列表中,然后按行绑定它们,添加逻辑TRUE并使用tidyr的{​​{1}}函数来获取结果。 当然,你也可以使用以下方法获得你的输出:

spread

list(d1, d2, d3) %>% bind_rows(.id="df") %>% mutate(n=V1) %>% spread(df, n) %>% select(-1) 1 2 3 1 PA0001 PA0001 PA0001 2 PA0002 <NA> <NA> 3 PA0003 PA0003 <NA> 4 PA0004 <NA> <NA> 5 PA0005 <NA> <NA> 6 <NA> PA0006 <NA> 7 <NA> PA0007 PA000 R中,您可以尝试:

base

答案 2 :(得分:2)

以下是基础R解决方案:

x <- lapply(list(test1, test2, test3), function(x) as.character(x[,1]))
xuni <- unique(unlist(x))
one_set <- function(i) { 
    idx <- which(is.na(match(xuni, x[[i]])))
    ans <- xuni
    ans[idx] <- NA
    return(ans)
}
res <- data.frame(
    test1=one_set(1),
    test2=one_set(2),
    test3=one_set(3),
    stringsAsFactors=FALSE
)
res

   test1  test2  test3
1 PA0001 PA0001 PA0001
2 PA0002 PA0002   <NA>
3 PA0003   <NA>   <NA>
4 PA0004 PA0004 PA0004
5 PA0005 PA0005 PA0005
6 PA0006   <NA>   <NA>
7   <NA> PA0007 PA0007
8   <NA>   <NA> PA0008

第一行将因子转换为字符,并将data.frame转换为每个data.frame中元素的列表x

第二行标识所有观察到的值。

函数one_set接受一个索引(要查看x的元素)并返回所需的输出列。