Как сохранить столбец B в строке x, если столбец A в строке x имеет значение - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть фрейм данных, подобный следующему:

ID     COL01_A  COL01_B   COL02_A COL02_B  ... COL12_A  COL12_B
1      01       19990101  03      20000101 ... FF       ""
2      03       20170810  FA      20120303 ... ""       ""
3      GG       19940508  DD      20000101 ... 03       20060808
4      03       20180101  09      20000101 ... ""       ""
5      GF       20171212  03      19990101 ... 02       20190101

Значения в столбцах типа A определяют, является ли значение в столбце типа B тем, которое я ищу.В этом случае интерес представляют значения «03».Есть двенадцать пар этих столбцов.Как видно из примера от COL01_A / COL01_B до COL12_A / COL12_B

Я искал способ создания нового столбца (давайте назовем его COL_X), в котором значение типа столбца B отражается, только если это столбец-близнецтипа A имеет значение «03».Для приведенного выше примера желаемый результат будет примерно таким:

ID  COL01_A  COL01_B   COL02_A COL02_B  ... COL12_A  COL12_B   COL_X
1   01       19990101  03      20000101 ... FF       ""        20000101
2   03       20170810  FA      20120303 ... ""       ""        20170810     
3   GG       19940508  DD      20000101 ... 03       20060808  20060808
4   03       20180101  09      20000101 ... ""       ""        20180101  
5   GF       20171212  03      19990101 ... 02       20190101  19990101

Сейчас я решил свою проблему, используя жестко длинное вложенное выражение ifelse, которое не совсем читаемо и не является хорошимпрактика (на мой взгляд).С точки зрения эффективности, это быстро, но я полагаю, это только потому, что данные не слишком массивны.Я также нашел другое решение, используя do.call(pmax(...)), но это решение требует, чтобы я очистил фрейм данных (используя операторы ifelse) и создал вспомогательный фрейм данных со всей другой информацией в строке.

Есть ли способ сделать это в наименьшем количестве возможных строк кода и / или без использования вспомогательных структур?Если бы решение использовало data.table или dplyr, это было бы замечательно.

Базовый воспроизводимый пример:

ID <- c(1,2,3,4,5)
DATA <- c('xxx', 'yyy', 'zzz','xyz','zxy')
COL01_A<- c('01','03','GG','03','GF')
COL01_B<- c('19990101','20170810','19940508','20180101','20171212')
COL02_A<- c('03','FA','DD','09','03')
COL02_B<- c('20000101','20120303','20000101','20000101','19990101')
COL03_A<- c('FF','','03','','02')
COL03_B<- c('','','20060808','','20190101')

df <- data.frame(ID, DATA, COL01_A,COL01_B,COL02_A,COL02_B,COL03_A,COL03_B)

, если есть несколько значений "03", COL_X должен иметь ""

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Идея состоит в том, чтобы использовать split.default и разделить фрейм данных на основе имен столбцов, а затем coalesce, то есть

l1 <- lapply(split.default(df[-c(1, 2)], sub('_.*', '', names(df[-c(1, 2)]))), function(i)
                                               ifelse(i[[1]] == '03', i[[2]][i[[1]] == '03'], NA)) 

Reduce(dplyr::coalesce, l1)

#[1] "20000101" "20180101" "20060808" "20180101" "20000101"

Если вы не хотите вызывать другую библиотеку только для однойфункция, за которой вы можете следовать этот ответ ,

Reduce(function(x, y) {
     i <- which(is.na(x))
     x[i] <- y[i]
     x
 }, l1)
#[1] "20000101" "20180101" "20060808" "20180101" "20000101"

Кража @ дескриптора RonakShah для нескольких 03 значений,

A_cols <- grep("_A$", names(df))
df$COL_X <- ifelse(rowSums(df[A_cols] == "03") > 1, "", df$COL_X)
0 голосов
/ 05 февраля 2019

Мы можем узнать A и B столбцы, используя grep, затем использовать max.col, чтобы найти индексы строк значений в A_cols, имеющих "03" в качестве значения, а затем подмножество соответствующего значения из B_cols.

A_cols <- grep("_A$", names(df))
B_cols <- grep("_B$", names(df))
df$COL_X <- df[B_cols][cbind(1:nrow(df), max.col(df[A_cols] == "03"))]

df

#  ID DATA COL01_A  COL01_B COL02_A  COL02_B COL03_A  COL03_B    COL_X
#1  1  xxx      01 19990101      03 20000101      FF          20000101
#2  2  yyy      03 20170810      FA 20120303                  20170810
#3  3  zzz      GG 19940508      DD 20000101      03 20060808 20060808
#4  4  xyz      03 20180101      09 20000101                  20180101
#5  5  zxy      GF 20171212      03 19990101      02 20190101 19990101

Как обновлено в комментарии, если в определенной строке более 1 значения "03", то мы хотим пустую строку в качестве вывода.Мы можем добавить дополнительную строку для этого условия после вышеупомянутого, и оно должно работать.

df$COL_X <- ifelse(rowSums(df[A_cols] == "03") > 1, "", df$COL_X)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...