Условный оператор, ссылающийся на отдельные строки - PullRequest
0 голосов
/ 29 августа 2018
data.frame(id = rep(letters[1:2], each  = 8), examID = as.character(c(11,11:17, 21:28)), baselineExam = c(rep(c(rbind('bl',c(11,14))), each = 2), c(rep('bl', 4), 21, 21, 24, 24)), examType = c("x", "x", "fu", "fu", "y", "z", "fu", "fu", "x", "x", "y", "z", "fu", "fu", "fu", "fu"), expected_col = c("x", "x", "x", "x", "y", "z", "y", "y", "x", "x", "y", "z", "x", "x", "z", "z"))

# the first four columns are my original data frame
# the last column shows the expected output.     

    id examID baselineExam examType expected_col
1   a     11           bl        x            x
2   a     11           bl        x            x
3   a     12           11       fu            x
4   a     13           11       fu            x
5   a     14           bl        y            y
6   a     15           bl        z            z
7   a     16           14       fu            y
8   a     17           14       fu            y
9   b     21           bl        x            x
10  b     22           bl        x            x
11  b     23           bl        y            y
12  b     24           bl        z            z
13  b     25           21       fu            x
14  b     26           21       fu            x
15  b     27           24       fu            z
16  b     28           24       fu            z

Существуют различные типы продольных экзаменов (examType) для каждого предмета (id). Каждый экзамен имеет свой уникальный идентификатор (examID). Только базовый экзамен содержит информацию об Экзамене. Последующие экзамены содержат только информацию «fu», но не правильный тип экзамена. Тем не менее, столбец baselineExam показывает, какой был базовый экзамен для соответствующего последующего наблюдения. Я хотел бы иметь столбец с правильным examType в каждой строке. (см. expected_col во фрейме данных)

Я застрял. Я не могу использовать что-то вроде if(baselineExam %in% examID) в сочетании с any, потому что нет группы, по которой я мог бы разделить эти экзамены.

Можно было бы получить индекс строки соответствующего «fu», посмотреть, какое значение это в «baselineExam», а затем найти это число в «examID», чтобы получить examType этой строки. .

Я попробовал вспомогательный столбец с индексным номером (должен быть и лучший способ), и я могу получить значение для базового экзамена в этой строке - но я не знаю, как затем условно получить значение в examType, когда examID (базовой строки) == baselineExam (последующей строки).

растворы базы R или dplyr предпочтительны, но открыты для всего


редактировать

Я изменил приведенные данные, потому что мои предыдущие выборочные данные не полностью отражали сложность реальных данных (я упрощенно их). К сожалению, ни решение @www, ни @akrun не сработало - мое плохо, потому что я не предоставил достаточно хороший образец :( Для каждого идентификатора экзамена может быть несколько строк (длинные данные, строки 1 и 2 в моем примере), а также несколько базовых экзаменов за другим до проведения последующих экзаменов.

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Один из вариантов - сгруппировать по 'id' и создать переменную группирования на основе вхождения 'bl', создать 'type' в качестве 'examType', что соответствует 'bl' в 'baselineExam'

library(dplyr)
df1 %>% 
    group_by(id, grp = cumsum(baselineExam == 'bl')) %>% 
    mutate(type = examType[baselineExam == 'bl']) %>% 
    ungroup %>% 
    select(-grp)
# A tibble: 8 x 5
#  id    examID baselineExam examType type 
#  <fct> <fct>  <fct>        <fct>    <fct>
#1 a     11     bl           x        x    
#2 a     12     11           fu       x    
#3 a     13     bl           y        y    
#4 a     14     13           fu       y    
#5 b     21     bl           x        x    
#6 b     22     21           fu       x    
#7 b     23     bl           z        z    
#8 b     24     23           fu       z    
0 голосов
/ 29 августа 2018

Решение с использованием пакета dplyr и tidyr. ключ должен заменить fu на NA, а затем использовать функцию fill, чтобы заполнить NA предыдущей строкой. mutate_if - это просто преобразование факторного столбца в символьный столбец. dat2 - окончательный результат.

library(dplyr)
library(tidyr)

dat2 <- dat %>%
  mutate_if(is.factor, as.character) %>%
  mutate(type = ifelse(examType %in% "fu", NA, examType)) %>%
  fill(type)
dat2
#   id examID baselineExam examType type
# 1  a     11           bl        x    x
# 2  a     12           11       fu    x
# 3  a     13           bl        y    y
# 4  a     14           13       fu    y
# 5  b     21           bl        x    x
# 6  b     22           21       fu    x
# 7  b     23           bl        z    z
# 8  b     24           23       fu    z

Обновление

Мы можем использовать пакет dplyr для достижения этой цели. Сначала задайте для фрейма данных известное examType, найдите строки с уникальной комбинацией между id, examID и examType, присоедините таблицу к исходному фрейму данных и используйте coalesce для объединения информации. .

library(dplyr)

dat2 <- dat %>%
  filter(!examType %in% "fu") %>%
  distinct(id, examID, examType) %>%
  rename(Type = examType) %>%
  left_join(dat, ., by = c("id", "baselineExam" = "examID")) %>%
  mutate(Type = coalesce(Type, examType))

dat2
#    id examID baselineExam examType Type
# 1   a     11           bl        x    x
# 2   a     11           bl        x    x
# 3   a     12           11       fu    x
# 4   a     13           11       fu    x
# 5   a     14           bl        y    y
# 6   a     15           bl        z    z
# 7   a     16           14       fu    y
# 8   a     17           14       fu    y
# 9   b     21           bl        x    x
# 10  b     22           bl        x    x
# 11  b     23           bl        y    y
# 12  b     24           bl        z    z
# 13  b     25           21       fu    x
# 14  b     26           21       fu    x
# 15  b     27           24       fu    z
# 16  b     28           24       fu    z

Данные для обновленного примера

dat <- data.frame(id = rep(letters[1:2], each  = 8), 
                  examID = as.character(c(11,11:17, 21:28)), 
                  baselineExam = c(rep(c(rbind('bl',c(11,14))), each = 2), c(rep('bl', 4), 21, 21, 24, 24)), 
                  examType = c("x", "x", "fu", "fu", "y", "z", "fu", "fu", "x", "x", "y", "z", "fu", "fu", "fu", "fu"),
                  stringsAsFactors = FALSE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...