Возьмите первое значение группы столбцов в R

#r #dplyr

Вопрос:

У меня есть кое-какие данные:

данные

 structure(list(WBC_BASELINE = c(2.9, NA, NA, 6.9, NA, NA, NA,  NA, NA, NA, 7.4, 12.8, NA, NA, NA, NA, NA, 4.2, NA, NA), WBC_FIRST = c(2.4,  14.8, 11, 7.3, 4.5, NA, NA, 6.1, 7.7, 16.2, 5.3, 10.3, 14.5,  NA, NA, 12.8, 3.7, 4.7, 16.6, 9.3), neuts_BASELINE = c(2, NA,  NA, 5.4, NA, NA, NA, NA, NA, NA, 4.96, 8.9, NA, NA, NA, NA, NA,  NA, NA, NA), neuts_FIRST = c(1.5, 13, 5.8, 4.5, 1.6, NA, NA,  1.7, 4.3, 9.3, 3.4, 5.8, 10.1, NA, NA, 9.7, 2.3, 3.5, 5, 8.2)), row.names = c(NA,  20L), class = "data.frame")  

В наборе данных у меня есть некоторые результаты анализа крови (в данном случае WBC и neuts взяты в 2 временных точках — исходная и первая). Я хочу выбрать базовое значение, если оно существует, иначе возьмите первое значение.

Я могу сделать это отдельно для WBC и neuts, но я хочу сделать это для 20 различных анализов крови без жесткого кодирования каждый раз…

Жесткий способ кодирования:

 data %gt;% mutate(WBC_first_value=ifelse(!is.na(WBC_BASELINE), WBC_BASELINE, WBC_FIRST)) %gt;%  mutate(neuts_first_value=ifelse(!is.na(neuts_BASELINE), neuts_BASELINE, neuts_FIRST))   

Пожалуйста, обратите внимание, что за каждым анализом крови всегда следует _BASELINE и _FIRST

Я был бы благодарен за любую помощь, пожалуйста!

Ответ №1:

Мы могли бы автоматизировать этот процесс с помощью некоторой обработки данных с использованием pivot_longer и pivot_wider в сочетании:

 library(dplyr) library(tidyr)  data %gt;%   mutate(rn = row_number()) %gt;%  pivot_longer(cols = -rn, names_to = c('grp', '.value'),  names_sep = "_") %gt;%   group_by(grp) %gt;%  transmute(rn, new = coalesce(BASELINE, FIRST)) %gt;%   pivot_wider(names_from = grp, values_from = new) %gt;%  select(-rn) %gt;%  bind_cols(data, .)  

выход:

 WBC_BASELINE WBC_FIRST neuts_BASELINE neuts_FIRST WBC neuts 1 2.9 2.4 2.00 1.5 2.9 2.00 2 NA 14.8 NA 13.0 14.8 13.00 3 NA 11.0 NA 5.8 11.0 5.80 4 6.9 7.3 5.40 4.5 6.9 5.40 5 NA 4.5 NA 1.6 4.5 1.60 6 NA NA NA NA NA NA 7 NA NA NA NA NA NA 8 NA 6.1 NA 1.7 6.1 1.70 9 NA 7.7 NA 4.3 7.7 4.30 10 NA 16.2 NA 9.3 16.2 9.30 11 7.4 5.3 4.96 3.4 7.4 4.96 12 12.8 10.3 8.90 5.8 12.8 8.90 13 NA 14.5 NA 10.1 14.5 10.10 14 NA NA NA NA NA NA 15 NA NA NA NA NA NA 16 NA 12.8 NA 9.7 12.8 9.70 17 NA 3.7 NA 2.3 3.7 2.30 18 4.2 4.7 NA 3.5 4.2 3.50 19 NA 16.6 NA 5.0 16.6 5.00 20 NA 9.3 NA 8.2 9.3 8.20  

Комментарии:

1. спасибо, я получаю ошибку — я пробовал distinct() , и это не исправляет ее… 1: Ожидается 2 штуки. Дополнительные фигуры отбрасываются в 2 ряда [20, 47]. 2: Значения не идентифицируются однозначно; выходные данные будут содержать столбцы списка. * Используйте values_fn = list для подавления этого предупреждения. * Используется values_fn = length для определения места возникновения дубликатов * Используется values_fn = {summary_fun} для обобщения дубликатов

2. С предоставленной базой данных он должен работать, как показано здесь. Если ваш исходный набор данных отличается, возможно, вы можете предоставить исходный кадр данных.?

3. Кажется, я все исправил. Я использовал столбец идентификатора, а также, как я думаю, были не уникальные значения. Спасибо за вашу помощь!

Ответ №2:

Вы могли бы сделать это с помощью петли!

 vars lt;- c("WBC", "neuts") for(v in vars){  df[,paste0(v, "_new")] lt;- ifelse(!is.na(df[,paste0(v, "_BASELINE")]), df[,paste0(v, "_BASELINE")], df[,paste0(v, "_FIRST")]) }  

Или с sapply :

 sapply(vars, function(v) ifelse(!is.na(df[,paste0(v, "_BASELINE")]),df[,paste0(v, "_BASELINE")], df[,paste0(v, "_FIRST")]))  

Также можно определить vars программно:

 vars lt;- unique(gsub(pattern = "^([A-Za-z] )_[A-Za-z] ", "\1", names(df)))