2017-03-08 82 views
1

我试图用单独的data.frame中的新值替换每个IndID的第一个值。请注意,每个IndID都有不同的观察值。用新值替换每个组的第一个数/因子

使用下面的示例代码,我想将number1number2的第一个值替换为dat2df中的相应列名称。在某些情况下,重置值为NA

set.seed(1) 
dat <- data.frame(IndID = rep(c("A","A","B","c","c","D"), each = 5), 
        number1 = sample(1:100,30), 
        number2 = sample(1:100,30)) 

dat2 <- data.frame(IndID = c("A","B","c","D"), 
        number1 = c(555,666,NA,888), 
        number2 = c(111,222,NA,444)) 

首选的结果将产生以下更有效和优雅的方法。我怀疑dplyr是一个合适的工具,但总是喜欢学习其他方法。

dat[1,2:3] <- c(555,111) 
dat[11,2:3] <- c(666,222) 
dat[16,2:3] <- c(NA,NA) 
dat[26,2:3] <- c(888,444) 
dat 
+0

哇。非常感激。我当然在关注的路线上...... –

回答

3

你可以尝试:

dat[match(dat2$IndID, dat$IndID),] <- dat2 
1
a1 <- lapply(split(dat, dat$IndID), function(x) { # split dat by IndID column 
    x[1, ] <- dat2[dat2$IndID %in% unique(x$IndID), ] # replace first row with the matching row of dat2 
    return(x)          # return modified data 
    }) 

do.call('rbind', a1) # combine all list elements together using rbind 

#  IndID number1 number2 
# A.1  A  555  111 
# A.2  A  37  60 
# A.3  A  57  100 
# A.4  A  89  19 
# A.5  A  20  80 
# A.6  A  86  64 
# A.7  A  97  75 
# A.8  A  62  11 
# A.9  A  58  67 
# A.10  A  6  38 
# B.11  B  666  222 
# B.12  B  16  58 
# B.13  B  61  69 
# B.14  B  34  98 
# B.15  B  67  46 
# c.16  c  NA  NA 
# c.17  c  88  2 
# c.18  c  83  40 
# c.19  c  32  61 
# c.20  c  63  57 
# c.21  c  75  39 
# c.22  c  17  88 
# c.23  c  51  35 
# c.24  c  10  97 
# c.25  c  21  6 
# D.26  D  888  444 
# D.27  D  1  24 
# D.28  D  28  91 
# D.29  D  81  48 
# D.30  D  25  29 
2

如果你不介意使用一个基础R的方法,你可以做到以下几点。您可以获得每个IndID的第一行索引,即ind。然后,你知道哪些行需要替换number1number2中的数字。使用索引并用dat2替换数字。

ind <- which(!duplicated(dat$IndID)) 
dat[ind, 2] <- dat2$number1 
dat[ind, 3] <- dat2$number2 


# IndID number1 number2 
#1  A  555  111 
#2  A  37  60 
#3  A  57  100 
#4  A  89  19 
#5  A  20  80 
#6  A  86  64 
#7  A  97  75 
#8  A  62  11 
#9  A  58  67 
#10  A  6  38 
#11  B  666  222 
#12  B  16  58 
#13  B  61  69 
#14  B  34  98 
#15  B  67  46 
#16  c  NA  NA 
#17  c  88  2 
#18  c  83  40 
#19  c  32  61 
#20  c  63  57 
#21  c  75  39 
#22  c  17  88 
#23  c  51  35 
#24  c  10  97 
#25  c  21  6 
#26  D  888  444 
#27  D  1  24 
#28  D  28  91 
#29  D  81  48 
#30  D  25  29 
+2

我认为'match'(在Jay的回答中)是可取的,因为它处理dat2中的IndID条目是(i)的顺序不同于dat和( ii)在dat中丢失。 – Frank

+1

@Frank我同意。 – jazzurro

4

随着data.table

library(data.table) 
DT = data.table(dat) 
DT[dat2, on=.(IndID), mult="first", `:=`(number1 = i.number1, number2 = i.number2)] 

你可以交替使用setDT(dat),而不是创建DT

顺便说一下,由于OP混合浮点数(在dat2中)和ints(在dat中),所以会引发警告。与base R不同,data.table在修改列时防止意外强制。


如果你想避免手动指定的列(如在@周杰伦的答案):

cols = setdiff(names(dat2), "IndID") 
DT[dat2, on=.(IndID), mult="first", (cols) := mget(sprintf("i.%s", cols))] 
相关问题