如何折叠 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
对相似的前缀列进行子集化,使用 pmax
和 na.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?
您可以尝试此解决方案,它将作用于 df1
和 df2
中存在的所有列:
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
和 df2
中选择在 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))
我的合并数据集如下所示:
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
对相似的前缀列进行子集化,使用 pmax
和 na.rm=TRUE
得到折叠的列,最后分配列表元素到 "df1".
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?
您可以尝试此解决方案,它将作用于 df1
和 df2
中存在的所有列:
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
和 df2
中选择在 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))