Копировать данные из одного столбца в другой столбец, если выполняется условие в другом столбце.

Я пытаюсь создать таблицу с заголовками study_id, Conflict и создать третий и четвертый столбцы, содержащие данные, соответствующие значению в столбце: Conflict

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

Заранее спасибо за любые указатели

df <- data.frame(study_id=c("1", "1", "4", "4", "5"), 
                 Conflict=c("WATER.START", "WATER.STOP", "OIL.START", "NA", "WATER.STOP"), 
                 Result=c("TRUE", "TRUE", "TRUE", "NA", "TRUE"))

df2 <- data.frame(study_id=c("1", "2", "3", "4", "5"), 
                  WATER.start=c(1, 1, 2, NA, 6), 
                  WATER.truestart=c(1, 1, 2, NA, 25), 
                  WATER.stop=c(33, 3, 2, NA, 8), 
                  WATER.truestop= c(34, 4, 2, NA, 8))

final <- left_join(df, df2, by ='study_id')

dd <- final %>% filter(Result == "TRUE" & Conflict == "WATER.START")
dd <- dd %>% subset(., Conflict == "WATER.START", 
                    select=c(study_id, Conflict, WATER.start, WATER.truestart))
dd <- dd %>% rename(initial=WATER.start) %>% rename(verification=WATER.truestart)

ee <- final %>% filter(Result == "TRUE" & Conflict == "WATER.STOP")
ee <- ee %>% subset(., Conflict == "WATER.STOP", 
                    select=c(study_id, Conflict, WATER.stop, WATER.truestop))
ee <- ee %>% rename(initial=WATER.stop) %>% rename(verification=WATER.truestop)

ff <- bind_rows(dd, ee)
gg <- ff %>% select(study_id, Conflict, initial, verification)

gg 
#   study_id    Conflict initial verification
# 1        1 WATER.START       1            1
# 2        1  WATER.STOP      33           34
# 3        5  WATER.STOP       8            8
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
Как сделать движок для футбольного матча? (простой вариант)
Как сделать движок для футбольного матча? (простой вариант)
Футбол. Для многих людей, живущих на земле, эта игра - больше, чем просто спорт. И эти люди всегда мечтают стать футболистом или менеджером. Но, к...
Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
Введение в раздел &quot;Заголовок&quot; в HTML
Введение в раздел "Заголовок" в HTML
Говорят, что лучшее о человеке можно увидеть только изнутри, и это относится и к веб-страницам HTML! Причина, по которой некоторые веб-страницы не...
2
0
87
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, кажется, что вы фокусируетесь только на c('WATER.START', 'WATER.STOP'), subset своем первом df. Затем для каждого MARGIN=1 (то есть каждой строки) мы apply анонимную функцию \(x), которая выбирает соответствующие столбцы df2, используя tolower для соответствия регистру и cbinds вместе. Наконец, переименуйте столбцы, используя setNames и rbind получившийся список.

subset(df, Conflict %in% c('WATER.START', 'WATER.STOP')) |>
  apply(MARGIN=1, \(x) {
    mt <- match(tolower(x[2]), tolower(names(df2)))
    cbind(t(x[1:2]), df2[df2$study_id == x[1], c(mt, mt + 1)]) |>
    setNames(c('study_id', 'Conflict', 'initial', 'verification'))
}) |> do.call(what=rbind)
#   study_id    Conflict initial verification
# 1        1 WATER.START       1            1
# 2        1  WATER.STOP      33           34
# 5        5  WATER.STOP       8            8

Вы также можете использовать словарь a (который может быть расширен до других уровней, которые вы можете использовать).

a <- c(WATER.START='WATER.start', WATER.STOP='WATER.stop')

subset(df, Conflict %in% c('WATER.START', 'WATER.STOP')) |>
  apply(MARGIN=1, \(x) {
    mt <- match(a[match(x[2], names(a))], names(df2))
    cbind(t(x[1:2]), df2[df2$study_id == x[1], c(mt, mt + 1)]) |>
      setNames(c('study_id', 'Conflict', 'initial', 'verification'))
  }) |> do.call(what=rbind)
#   study_id    Conflict initial verification
# 1        1 WATER.START       1            1
# 2        1  WATER.STOP      33           34
# 5        5  WATER.STOP       8            8

Ваше здоровье. В этом подходе используется тот факт, что WATER.START также находится во втором кадре данных, все в частичном нижнем регистре, а WATER.truestart находится с помощью mt + 1. Каким был бы подход, если бы WATER.START в первом кадре данных не смог изменить в простом было, изменив на нижний регистр. Например, WATER.START на самом деле назывался Fluid.on.

GJW 19.02.2023 03:41

Чуть менее элегантным способом было использование fct_recode df <- data.frame(study_id = (c("1","1","4","4","5")), Conflict = (c("fluid_a_on ","fluid_a_off","OIL.START","NA","WATER.STOP")‌​), Результат = (c("ИСТИНА","ИСТИНА","ИСТИНА","NA","ИСТИНА" ))) df <- df %>% mutate(Conflict = fct_recode(Conflict, "WATER.START" = "fluid_a_on", "WATER.STOP" = "fluid_a_off")) df Если есть альтернативный подход, мне было бы интересно знать. Ваше здоровье

GJW 19.02.2023 05:30

@GJW Чтобы предоставить информацию, которую вы можете использовать в словаре, см. Обновление. Мы могли бы сделать здесь много необычных вещей, но, возможно, было бы лучше решить эту проблему заранее в предварительной обработке очистки данных, где соответствующие элементы получают одинаковые метки.

jay.sf 19.02.2023 06:28

Блестящие указатели. При применении этого кода к моему кадру данных я получаю следующую ошибку «Ошибка в data.frame(..., check.names = FALSE): аргументы подразумевают разное количество строк: 1, 0 Вызывается из: data.frame(... , check.names = FALSE)" Когда я меняю cbind на bind_cols, я перестаю получать повторяющуюся ошибку, однако код не возвращает вывод для всех строк. Мой эквивалент «df» содержит меньше строк, чем мой эквивалент «df2», а df2 содержит много NA. И df, и df2 являются кадрами данных.

GJW 20.02.2023 15:01

Код @GJW у меня работает, не знаю, в чем причина проблемы, не могу воспроизвести. Возможно, у вас есть таблички вместо фреймов данных, попробуйте изменить их на фреймы данных, как показано в OP.

jay.sf 20.02.2023 15:14

Извините, я не мог скопировать «мои данные» из-за ограничений по количеству символов, поэтому я снова опубликовал — с исходными данными и кодом. Ошибка заключается где-то в том, как представлены мои данные, в отличие от вашего решения, подробно описанного выше.

GJW 20.02.2023 16:36

Другие вопросы по теме