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

How to collapse NA and merge multiple columns into one column

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

    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 等其他列来合并这两列

感谢您的帮助!

如果我正确理解了您的最终产品,使用 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

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

想法是创建一个模式 ('pat') 来指定需要折叠的列的 "prefixes"。获取具有 grep 的那些列的数字索引 ("indx")。从原始数据集 ("df") 中删除列并创建新数据集 "df1"。使用 lapply 循环 "pat",使用 grep 对相似的前缀列进行子集化,使用 pmaxna.rm=TRUE 得到折叠的列,最后分配列表元素到 "df1".

中的新列 ("V1, V2")
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 查找非 NA 值的 "row index" 并获取具有 "row/column" 索引的元素。

 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"))

1) Is there any way I can merge two datasets without producing 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])

它从 df1df2 中选择在 V1 列中具有共同值的行,然后使用第一个数据集中的相应值填充 NA彼此列的第二个数据集。

2) If I cannot merge these two datasets without V1.x and V1.y, then how can I collapse NAs and merge these two columns?

如果您已经合并了数据,可以试试这个解决方案(它仅适用于 V1 列):

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