我正在尝试执行以下操作,我最初发布了一个更简单的版本,认为它可以概括,但现在意识到它不会,所以我在这里重新发布问题
原始问题(和解决方案)可以在这里找到:Matching data from one data frame to another
我有两个数据框,dfa 和 dfb
IDa <- c(1,2,3)
score1a <- c(5,10,1)
score2a <- c(NA,8,NA)
score3a <- c(NA,NA,13)
score1b <- c(NA,4,9)
score2b <- c(2,3,NA)
score2c <- c(1,5,1)
score3c <- c(6,NA,1)
dfa <- data.frame(IDa,score1a,score2a,score3a,score1b,score2b,score2c,score3c)
IDb <- c(1,1,1,2,2,3)
timeb <- c(1,2,3,2,3,3)
dfb <- data.frame(IDb,timeb)
在score1a中,'1'代表dfb中的时间b = 1,'a'代表第一种测试类型(因此有3种类型的测试,a,b,c和3个时间点1,2,3)
我想从 dfa 获取数据并将其添加到 dfb 以创建类似下面 dfc 的内容(请注意 dfc 的前两列与 dfb 相同)
IDc <- c(1,1,1,2,2,3)
timec <- c(1,2,3,2,3,3)
scorea <- c(5,NA,NA,8,NA,13)
scoreb <- c(NA,2,NA,3,NA,NA)
scorec <- c(NA,1,6,5,NA,1)
dfc <- data.frame(IDc, timec, scorea, scoreb, scorec)
希望这是有道理的,非常感谢您对此提供的任何帮助!
最佳答案
这是使用 dplyr 和 tidyr 的选项:
require(dplyr)
require(tidyr)
gather(dfa, xx, timea, -IDa) %>%
mutate(xx = as.character(xx),
x = gsub("[0-9]", "", xx)) %>%
spread(x, timea) %>%
mutate(xx = as.numeric(gsub("[a-zA-Z]", "", xx))) %>%
group_by(IDa, xx) %>%
summarise_each(funs(first(.[!is.na(.)]))) %>%
left_join(dfb, ., by = c("IDb" = "IDa", "timeb" = "xx"))
# IDb timeb scorea scoreb scorec
#1 1 1 5 NA NA
#2 1 2 NA 2 1
#3 1 3 NA NA 6
#4 2 2 8 3 5
#5 2 3 NA NA NA
#6 3 3 13 NA 1
执行以下步骤(每行代码):
- 收集:将数据从宽格式重新整形(收集)为长格式,新列将命名为“xx”和“timea”
- Mutate:将“xx”列变成字符列(之前是一个因子)
- 仍然发生变化:根据“xx”列创建一个新列“x”,但 xx 中的所有数字都将被删除
- 扩展:根据新的“x”列将数据从长变为宽
- Mutate:删除“xx”中的所有字符,并将其余的(字符格式的数字)存储为数字
- group_by:按“IDa”和“xx”对数据进行分组
- summarise_each:在每个组内(按 IDa 和 xx),对于除分组变量 IDa 和 xx 之外的每一列:采用 第一个 元素,该元素不 NA。更明确地说:
.[!is.na(.)]
从数据中删除所有 NA 条目,然后包裹在其周围的first()
函数获取第一个元素没有 NA 的数据。一般来说,summarise
和summarise_each
会将每个组的数据分解为 1 行(在本例中将保存第一个非 NA 条目)。 - left_join:分别通过 ID 列、timeb 和 xx 与之前计算的数据(注意 left_join 内的顺序,这在这里很重要)执行 dfb 左连接。
编辑2
下面是一些示例,可帮助您更好地理解 first(.[!is.na(.)])
部分的作用。请记住,在代码中,.
表示传递给函数的分组数据(相当于我在下面的示例中称为 x
)。
set.seed(99)
x <- sample(10) #create a vector with random numbers
x
#[1] 6 2 10 7 4 5 3 1 8 9
x[sample(10, 4, replace = F)] <- NA # add some NAs
x
#[1] 6 NA 10 7 NA NA 3 1 NA 9
is.na(x) # is the value in each in index/place of x equal to NA?
#[1] FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE TRUE FALSE
x[is.na(x)] # show me the values of x which are NA (of course, they are NA)
#[1] NA NA NA NA
x[!is.na(x)] # show me the values of x which are not NA (== remove NAs)
#[1] 6 10 7 3 1 9
dplyr::first(x[!is.na(x)]) # of all the values in x which are not NA, return the first one
#[1] 6
x[!is.na(x)][1] # this is equivalent to the previous line but using [1] instead of first()
#[1] 6
head(x[!is.na(x)], 1) # this is also equivalent of the two previous lines but using head(..., 1)
#[1] 6
希望有帮助。
关于r - 将一个数据帧中的数据匹配到另一个数据帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27132060/