Заполните NA до числа, после этого заполните 0 - PullRequest
1 голос
/ 12 февраля 2020

Мне нужно преобразовать NA в 0 после того, как число появится в таймере ie. Вот пример:

c1 <- c(1,NA,NA,NA,NA,1,2,NA,NA,NA,5,NA,NA)
c2 <- c(2,NA,NA,10,30,NA,NA,NA,NA,4,1,2,NA)
c3 <- c(3,NA,NA,NA,NA,NA,NA,NA,NA,1,NA,NA,NA)
x <- data.frame(rbind(c1,c2,c3))
colnames(x) <- c("ID","Jan01","Feb01","Mar01","Apr01","May01","Jun01","Jul01","Aug01","Sep01","Oct01","Nov01","Dec01")
x

#    ID Jan01 Feb01 Mar01 Apr01 May01 Jun01 Jul01 Aug01 Sep01 Oct01 Nov01 Dec01
# c1  1    NA    NA    NA    NA     1     2    NA    NA    NA     5    NA    NA
# c2  2    NA    NA    10    30    NA    NA    NA    NA     4     1     2    NA
# c3  3    NA    NA    NA    NA    NA    NA    NA    NA     1     NA   NA    NA

И это то, что я ожидаю:

c11 <- c(1,NA,NA,NA,NA,1,2,0,0,0,5,0,0)
c22 <- c(2,NA,NA,10,30,0,0,0,0,4,1,2,0)
c33 <- c(3,NA,NA,NA,NA,NA,NA,NA,NA,1,0,0,0)
y <- data.frame(rbind(c11,c22,c33))
colnames(y) <- c("ID","Jan01","Feb01","Mar01","Apr01","May01","Jun01","Jul01","Aug01","Sep01","Oct01","Nov01","Dec01")
y

#     ID Jan01 Feb01 Mar01 Apr01 May01 Jun01 Jul01 Aug01 Sep01 Oct01 Nov01 Dec01
# c11  1    NA    NA    NA    NA     1     2     0     0     0     5     0     0
# c22  2    NA    NA    10    30     0     0     0     0     4     1     2     0
# c33  3    NA    NA    NA    NA    NA    NA    NA    NA     1     0     0     0

Кто-то, кто знает, как это сделать? спасибо!

Ответы [ 3 ]

4 голосов
/ 12 февраля 2020

A base опция:

t(apply(x[,-1], 1, function(x) ifelse(is.na(x) & cumsum(!is.na(x)) >= 1, 0, x)))

Выход:

   Jan01 Feb01 Mar01 Apr01 May01 Jun01 Jul01 Aug01 Sep01 Oct01 Nov01 Dec01
c1    NA    NA    NA    NA     1     2     0     0     0     5     0     0
c2    NA    NA    10    30     0     0     0     0     4     1     2     0
c3    NA    NA    NA    NA    NA    NA    NA    NA     1     0     0     0

Как указывал @markus, для повышения производительности используйте replace вместо ifelse, например :

t(apply(x[,-1], 1, function(x) replace(x, is.na(x) & cumsum(!is.na(x)) >= 1, 0)))
3 голосов
/ 12 февраля 2020

Я переместился обратно в «широкую» форму после замены NA, чтобы соответствовать желаемому выводу, но в качестве примечания, вероятно, лучше в любом случае сохранить это в длинной форме.

library(dplyr)

long <- 
  x %>% 
    pivot_longer(-ID) %>% 
    group_by(ID) %>% 
    mutate(value = ifelse(cummax(!is.na(value)), coalesce(value, 0), value))

long %>% 
  pivot_wider(ID, name)


# # A tibble: 3 x 13
# # Groups:   ID [3]
#      ID Jan01 Feb01 Mar01 Apr01 May01 Jun01 Jul01 Aug01 Sep01 Oct01 Nov01
#   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1     1    NA    NA    NA    NA     1     2     0     0     0     5     0
# 2     2    NA    NA    10    30     0     0     0     0     4     1     2
# 3     3    NA    NA    NA    NA    NA    NA    NA    NA     1     0     0
# # ... with 1 more variable: Dec01 <dbl>
0 голосов
/ 13 февраля 2020

Другое базовое решение R, использующее aggregate + col + replace, то есть

idx <- aggregate(col~row,which(!is.na(x[-1]),arr.ind = T),min)
xout <- cbind(x[1],replace(x[-1],col(x[-1])>=idx$col & is.na(x[-1]),0))

, такое что

> xout
   ID Jan01 Feb01 Mar01 Apr01 May01 Jun01 Jul01 Aug01 Sep01 Oct01 Nov01 Dec01
c1  1    NA    NA    NA    NA     1     2     0     0     0     5     0     0
c2  2    NA    NA    10    30     0     0     0     0     4     1     2     0
c3  3    NA    NA    NA    NA    NA    NA    NA    NA     1     0     0     0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...