如何折叠NA并将多个列合并为一列

时间:2015-01-29 19:00:18

标签: r merge collapse

我有一个合并的数据集如下所示:

    V3    V1.x               V2.x   V1.y                 V2.y   V982 V2163 
1  10075  Whitten Jamie L.   1225    <NA>                NA     2     2   
2  10421  Yates Sidney R.    1252    Yates Sidney R.     1252   2     0      
3  10520  Gonzalez Henry B.   445    Gonzalez Henry B.   445    0     0       
4  10573  Brown George E.Jr.  134    Brown George E.Jr.  134    0     0    
5  29584  <NA>                NA     Cubin  Barbara      254    0     0

我通过匹配V3合并了两个数据集。如您所见,两个数据集都有V1和V2变量,这两个不相同。

我有两个问题。

1)有没有办法在不生成V1.x V1.y的情况下合并两个数据集?我的意思是我想知道是否有任何方法可以让V1看起来像这样

V1
Whitten Jamie L.
Yates Sidney R.
Gonzalez Henry B.
Brown George E.Jr.
Cubin  Barbara

我使用了像merge(df1, df2, by=c("V3")之类的简单合并命令。

2)如果我不能在没有V1.x和V1.y的情况下合并这两个数据集,那么如何折叠NA并合并这两列呢?

我在论坛中搜索了其他问题,我找到了类似的命令 cbind(data[1], mycol = na.omit(unlist(data[-1])))  na.omit(stack(df))df2<-apply(df,1,function(x) x[!is.na(x)])。但他们都不能很好地工作。当我没有像V982 V3或V2163这样不相关的列时,这些命令似乎有效。我不知道如何通过匹配NA来保存其他列,如V982 V2163等,从而合并这两列。

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

  

1)有没有办法在不生成V1.x的情况下合并两个数据集   V1.y?

您可以尝试使用此解决方案,该解决方案将对df1df2中存在的所有列起作用:

d1 <- df1[df1$V3 %in% df2$V3,]
d2 <- df2[df2$V3 %in% df1$V3,]

m <- match(d2$V3,d1$V3)
z <- sapply(names(d1),function(s) ifelse(is.na(d1[,s]),d2[m,s],d1[,s]))
result <- cbind(z,d2[m,setdiff(names(d2),names(d1)),drop=F])

它使用df1列中的常用值从df2V1中选择行,然后使用第二个数据中的相应值从第一个数据集中填充NA为彼此列设置。

  

2)如果我不能在没有V1.x和V1.y的情况下合并这两个数据集,那么   如何折叠NA并合并这两列?

如果您已合并数据,则可以尝试此解决方案(仅适用于V1列):

df$V1 <- with(df,ifelse(is.na(V1.x),V1.y,V1.x))

答案 1 :(得分:0)

如果我正确理解您的最终产品,请使用dplyr,这很简单:

df1 %>%
    select(V3, V982) %>%
    left_join(select(df2,V3,V2163), by=V3)

给出:

     V3 V982 V2163
1 10075    2     2
2 10421    2     0
3 10520    0     0
4 10573    0     0
5 29584    0     0

答案 2 :(得分:0)

在这里,我在回答第二个问题时提供了合并的数据集。

我们的想法是创建一个模式(&#39; pat&#39;)来指定&#34;前缀&#34;需要折叠的列。获取grep列的数字索引(&#34; indx&#34;)。从原始数据集中删除列(&#34; df&#34;)并创建新数据集&#34; df1&#34;。循环播放&#34; pat&#34;使用lapply,使用grep对类似的前缀列进行子集,使用pmaxna.rm=TRUE来获取折叠列,最后将列表元素分配给新列(&#34) ; V1,V2&#34;)&#34; df1&#34;。

pat <- paste0('^V', 1:2, '..$')
indx <- grep(paste(pat, collapse='|'), names(df))
df1 <- df[-indx]
df1[paste0('V',1:2)] <- lapply(pat, function(x) do.call(pmax,
                           c(df[grep(x, names(df))], na.rm=TRUE)))
df1
#     V3 V982 V2163                 V1   V2
#1 10075    2     2   Whitten Jamie L. 1225
#2 10421    2     0    Yates Sidney R. 1252
#3 10520    0     0  Gonzalez Henry B.  445
#4 10573    0     0 Brown George E.Jr.  134
#5 29584    0     0     Cubin  Barbara  254

或者您可以使用max.col查找&#34;行索引&#34;非NA值并使用&#34; row / column&#34;获取元素索引。

 df1[paste0('V', 1:2)] <- lapply(pat, function(x) {
            x1 <- df[grep(x, names(df))]
            x1[cbind(1:nrow(x1), max.col(!is.na(x1)))]})

数据

df <- structure(list(V3 = c(10075L, 10421L, 10520L, 10573L, 29584L), 
V1.x = c("Whitten Jamie L.", "Yates Sidney R.", "Gonzalez Henry B.", 
"Brown George E.Jr.", NA), V2.x = c(1225L, 1252L, 445L, 134L, 
NA), V1.y = c(NA, "Yates Sidney R.", "Gonzalez Henry B.", 
"Brown George E.Jr.", "Cubin  Barbara"), V2.y = c(NA, 1252L, 
445L, 134L, 254L), V982 = c(2L, 2L, 0L, 0L, 0L), V2163 = c(2L, 
0L, 0L, 0L, 0L)), .Names = c("V3", "V1.x", "V2.x", "V1.y", 
"V2.y", "V982", "V2163"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5"))