Объединение фреймов данных так, чтобы значения в одном фрейме данных вставлялись в соответствующие номера строк в другом - PullRequest
0 голосов
/ 07 марта 2019

Я хочу изменить формат набора данных определенным образом.Скажем, у меня есть список данных, указывающих, когда и сколько раз участники посещали сеансы couselling.Они могли посещать максимум три сессии в любое время в течение двенадцати недель.Скажем, их данные записываются примерно так:

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

Но я хочу длинный набор данных, в котором у каждого человека есть ряд для каждой из двенадцати недель, которые онимогли бы присутствовать, например, так:

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

Таким образом, данные участника А выглядят так:

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

Я бы хотел как-то объединить два, чтобы числа в столбце week1df1 соответствует своей соответствующей строке в 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

Ответы [ 3 ]

1 голос
/ 07 марта 2019

Один подход с использованием слияния:

# 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)
1 голос
/ 07 марта 2019

Вы можете расширить исходный файл data.frame, используя tidyr::complete, поэтому вам не нужно объединять, просто определите 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
1 голос
/ 07 марта 2019
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
}))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...