r - 将一个数据帧中的数据匹配到另一个数据帧

标签 r reshape

我正在尝试执行以下操作,我最初发布了一个更简单的版本,认为它可以概括,但现在意识到它不会,所以我在这里重新发布问题

原始问题(和解决方案)可以在这里找到: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

执行以下步骤(每行代码):

  1. 收集:将数据从宽格式重新整形(收集)为长格式,新列将命名为“xx”和“timea”
  2. Mutate:将“xx”列变成字符列(之前是一个因子)
  3. 仍然发生变化:根据“xx”列创建一个新列“x”,但 xx 中的所有数字都将被删除
  4. 扩展:根据新的“x”列将数据从长变为宽
  5. Mutate:删除“xx”中的所有字符,并将其余的(字符格式的数字)存储为数字
  6. group_by:按“IDa”和“xx”对数据进行分组
  7. summarise_each:在每个组内(按 IDa 和 xx),对于除分组变量 IDa 和 xx 之外的每一列:采用 第一个 元素,该元素 NA。更明确地说:.[!is.na(.)] 从数据中删除所有 NA 条目,然后包裹在其周围的 first() 函数获取第一个元素没有 NA 的数据。一般来说,summarisesummarise_each 会将每个组的数据分解为 1 行(在本例中将保存第一个非 NA 条目)。
  8. 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/

相关文章:

r - 如何在不聚合的情况下在 reshape 中使用 "cast"

r - 如何透视表以从 R 中的可变行值创建列

r - 如何反转R中模式中数据帧的顺序

r - 使用另一列中给定条件的两列组合展开 data.table

r - 在大数据集上按组分割和展开网格

r - 如何在ggplot2中组合排斥标签和阴影或光环文本?

r - 将重复的列集收集到单个列中

r 向条形图添加线条或线段

python - 使用分组数据 reshape Pandas Dataframe(从长到宽)

reshape 将两列添加到 data.frame