简体   繁体   中英

R: two data frame merge

I want to merge two data frame, but there are some row names repeated. If the numbers of row name in two data frame are different, I hope the it can show "NA" in the less one column.

My example:

test1 <- data.frame(name = c("A", "B", "C", "C", "C", "D"), n1 = c("15", "14", "13", "12", "11", "10"))
test2 <- data.frame(name = c("A", "B", "B", "C", "C", "D"), n1 = c("30", "31", "33", "39", "38", "40")) 

Then I merge by name, I got

name n1.x n1.y

 A 15 30 B 14 31 B 14 33 C 13 39 C 13 38 C 12 39 C 12 38 C 11 39 C 11 38 D 10 40 

It will repeating What I want to is

name n1.x n1.y

 A 15 30 B 14 31 B NA 33 C 13 39 C 12 38 C 11 NA D 10 40 

What Command should I use? Thank you very much!

Try:

test1$indx <- with(test1, ave(1:nrow(test1), name, FUN=seq_along))
test2$indx <- with(test2, ave(1:nrow(test2), name, FUN=seq_along))
merge(test1, test2, by=c("name","indx"),all=T)[,-2]
 #   name n1.x n1.y
# 1    A   15   30
# 2    B   14   31
# 3    B <NA>   33
# 4    C   13   39
# 5    C   12   38
# 6    C   11 <NA>
# 7    D   10   40

I will post this before data.table.people come in with a slick, scalable and quicl solution.

Be warned, that this works for provided data set. You should examine the results of your production code carefully.

What the below code does is sticks together values for a common level. The rest is just bookkeeping.

ml <- vector("list", length(unique(test1$name)))
names(ml) <- unique(test1$name)

for (i in unique(test1$name)) {
  o1 <- test1[test1$name %in% i, , drop = FALSE]
  o2 <- test2[test2$name %in% i, , drop = FALSE]
  o.max <- max(c(nrow(o1), nrow(o2)))
  nc <- ifelse(o.max == 1, 2, o.max*2)
  out <- matrix(rep(NA, times = nc), nrow = nc/2)
  out[1:nrow(o1), 1] <- as.numeric(as.character(o1$n1))
  out[1:nrow(o2), 2] <- as.numeric(as.character(o2$n1))

  ml[[i]] <- out
}

count.each <- sapply(ml, nrow)
result <- do.call("rbind", ml)
colnames(result) <- c("n1.x", "n1.y")
data.frame(name = rep(names(ml), count.each), result)

  name n1.x n1.y
1    A   15   30
2    B   14   31
3    B   NA   33
4    C   13   39
5    C   12   38
6    C   11   NA
7    D   10   40

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM