【问题标题】:Merging data frames so that values in one data frame are inserted in matching row numbers in another合并数据帧,以便将一个数据帧中的值插入到另一个数据帧的匹配行号中
【发布时间】:2019-03-07 05:41:21
【问题描述】:

我想以某种方式更改数据集的格式。假设我有一个数据列表,表明参与者参加辅导课程的时间和次数。他们可以在十二周内的任何时间参加最多三个会议。说他们的数据是这样记录的

set.seed(01234)
df1 <- data.frame(id = rep(LETTERS[1:4], each = 3),
                  session = rep(paste0("session", 1:3), length.out = 12),
                  week1 = c(sort(sample(1:12, 3, replace = F)), 
                           sort(sample(1:12, 3, replace = F)), 
                           sort(sample(1:12, 3, replace = F)), 
                           sort(sample(1:12, 3, replace = F)))) 
df1$week1[c(3,8,9,12)] <- NA # insert some NAs representing sessions that weren't attended

数据集看起来像这样

#    id  session week1
# 1   A session1     2
# 2   A session2     7
# 3   A session3    NA
# 4   B session1     7
# 5   B session2     8
# 6   B session3    10
# 7   C session1     1
# 8   C session2    NA
# 9   C session3    NA
# 10  D session1     6
# 11  D session2     7
# 12  D session3    NA

但我想要一个长数据集,其中每个人在他们本可以参加的 12 周中的每一周都有一行,就像这样

df2 <- data.frame(id = rep(LETTERS[1:4], each = 12),
                  week2 = rep(1:12, times = 4))

所以参与者 A 的数据是这样的

df2[1:12,]

#    id week2
# 1   A     1
# 2   A     2
# 3   A     3
# 4   A     4
# 5   A     5
# 6   A     6
# 7   A     7
# 8   A     8
# 9   A     9
# 10  A    10
# 11  A    11
# 12  A    12

我想以某种方式合并这两者,以便 df1 的 week1 列中的数字与 df2 中的相应行匹配,理想情况下是这样的(示例仅限参与者 A)

data.frame(id = rep("A", 12),
           week = 1:12,
           attended = c(0,1,0,0,0,0,1,0,0,0,0,0))

#    id week attended
# 1   A    1        0
# 2   A    2        1
# 3   A    3        0
# 4   A    4        0
# 5   A    5        0
# 6   A    6        0
# 7   A    7        1
# 8   A    8        0
# 9   A    9        0
# 10  A   10        0
# 11  A   11        0
# 12  A   12        0

【问题讨论】:

    标签: r


    【解决方案1】:

    一种利用合并的方法:

    # merge the 2 dataframes
    names(df2)[2] <- "week"
    names(df1)[3] <- "week"
    df <- merge(df2, df1, by=c("id", "week"), all.x=T)
    
    # replace 'session' with 1s and 0s
    df$session <- !is.na(df$session)
    

    【讨论】:

      【解决方案2】:
      do.call(rbind, lapply(split(df2, df2$id), function(x){
          x$attended = as.integer(x$week2 %in% df1$week1[df1$id == x$id[1]])
          x
      }))
      

      【讨论】:

      • 出色的答案@d.b。但不幸的是,我真的不明白发生了什么。我是一个相对菜鸟的错,而不是你作为黑带的错。如果 Dan Y 没有这么快就插话你就会得到接受。
      【解决方案3】:

      您可以使用tidyr::complete 扩展原始data.frame,因此您不需要合并,只需将week1 定义为具有正确级别数的因子:

      library(dplyr)
      library(tidyr)
      
      df1 %>% 
        group_by(id) %>%
        mutate(week1 = factor(week1, levels = 1:12), 
               session = !is.na(session)) %>%
        complete(week1, fill = list(session = 0)) 
      
      # A tibble: 52 x 3
      # Groups:   id [4]
         id    week1 session
         <fct> <fct>   <dbl>
       1 A     1           0
       2 A     2           1
       3 A     3           0
       4 A     4           0
       5 A     5           0
       6 A     6           0
       7 A     7           1
       8 A     8           0
       9 A     9           0
      10 A     10          0
      # ... with 42 more rows
      

      【讨论】:

      • 不错。你显然比我探索了更多的 tidyverse。
      猜你喜欢
      • 1970-01-01
      • 2021-05-12
      • 2021-04-26
      • 1970-01-01
      • 2013-02-24
      • 2021-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多