dplyr: нужна помощь в возврате индекса столбца первого значения не-NA в каждой строке - PullRequest
4 голосов
/ 14 мая 2019

Я недавно начал пытаться сделать весь мой код в тидиверсе. Это иногда приводило меня к трудностям. Вот простая задача, которую я не смог выполнить в тидиверсе: мне нужен столбец в фрейме данных, который возвращает индекс положения первого значения, отличного от na, слева. Кто-нибудь знает, как добиться этого в dplyr с помощью mutate?

Вот желаемый результат.

data.frame(                           
"X1"=c(100,rep(NA,8)),
"X2"=c(NA,10,rep(NA,7)),
"X3"=c(NA,NA,1000,1000,rep(NA,5)),
"X4"=c(rep(NA,4),25,50,10,40,50),
"FirstNonNaPosition"=c(1,2,3,3,4,4,4,4,4)
)

Ответы [ 3 ]

4 голосов
/ 14 мая 2019

Также возможна base R:

apply(df, 1, which.max)

[1] 1 2 3 3 4 4 4 4 4

То же самое с dplyr:

df %>%
 mutate(FirstNonNaPosition = apply(., 1, which.max))

Модификация сценария, упомянутого @Andrew:

apply(df, 1, function(x) which.max(!is.na(x)))

То же самое с dplyr:

df %>%
 mutate(FirstNonNaPosition = apply(., 1, function(x) which.max(!is.na(x))))
4 голосов
/ 14 мая 2019

Более простой и эффективный вариант base R будет max.col после замены элементов NA на 0

max.col(replace(df2[1:4], is.na(df2[1:4]), 0), 'first')

Или даже

df2$FirstNonNaPosition <- max.col(!is.na(df2[1:4]), "first")
df2$FirstNonNaPosition
#[1] 1 2 3 3 4 4 4 4 4

С tidyverse возможный вариант: pmap

df2 %>% 
  mutate(FirstNonNaPosition = pmap_int(.[-5], ~ 
                          which.max(!is.na(c(...)))))

Или обернуть max.col

df2 %>% 
   mutate(FirstNonNaPosition = max.col(!is.na(.[-5]), 'first'))

данные

df2 <- structure(list(X1 = c(100, NA, NA, NA, NA, NA, NA, NA, NA), X2 = c(NA, 
10, NA, NA, NA, NA, NA, NA, NA), X3 = c(NA, NA, 1000, 1000, NA, 
NA, NA, NA, NA), X4 = c(NA, NA, NA, NA, 25, 50, 10, 40, 50), 
    FirstNonNaPosition = c(1, 2, 3, 3, 4, 4, 4, 4, 4)), 
    class = "data.frame", row.names = c(NA, 
-9L))
3 голосов
/ 14 мая 2019

Вы также можете использовать apply:

data.frame(                           
"X1"=c(100,rep(NA,8)),
"X2"=c(NA,10,rep(NA,7)),
"X3"=c(NA,NA,1000,1000,rep(NA,5)),
"X4"=c(rep(NA,4),25,50,10,40,50),
"FirstNonNaPosition"=c(1,2,3,3,4,4,4,4,4)
) %>%
  mutate(First_Non_NA_Pos = apply(., 1, function(x) which(!is.na(x))[1]))

   X1 X2   X3 X4 FirstNonNaPosition First_Non_NA_Pos
1 100 NA   NA NA                  1                1
2  NA 10   NA NA                  2                2
3  NA NA 1000 NA                  3                3
4  NA NA 1000 NA                  3                3
5  NA NA   NA 25                  4                4
6  NA NA   NA 50                  4                4
7  NA NA   NA 10                  4                4
8  NA NA   NA 40                  4                4
9  NA NA   NA 50                  4                4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...