Замените цикл более эффективным решением

#r #performance #loops

#r #Производительность #циклы

Вопрос:

Итак, мои данные выглядят так:

 test <- structure(list(value = c(0, 781, 1109, 57, 250, 541, 533, 320, 
322, 1033, 291, 2213, 1845, 618, 271, 525, 88, 1354, 217, 820, 
786, 119, 41, 316, 153, 378, 172, 615, 383, 168, 1448, 824, 85, 
224310, 1186, 1488, 244, 368, 133, 488, 118, 4505, 1411, 649, 
690, 548, 226, 393, 1042, 92, 521, 212, 1015, 380, 2944, 54376, 
1396, 429, 2725, 171, 1874, 87, 547, 488, 140, 169, 237, 1749, 
1144, 156, 843, 116, 313, 601, 679, 464, 1092, 178, 28, 57, 550, 
498, 64, 48143, 352, 4100, 232, 1936, 189, 940, 180, 1051, 2917, 
2397, 229, 802, 540, 297, 505, 1649), count = c(1L, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 2L, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, 3L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 4L, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
)), row.names = c(NA, -100L), class = c("tbl_df", "tbl", "data.frame"
))
 

столбец value содержит несколько случайных значений, а столбец count в основном заполнен NA s. В конце концов, мне нужно, чтобы каждый NA вход count был таким же, как и последний, которого не NA было. Итак, первые несколько строк должны быть count == 1 и как только count в 2 них должны быть внесены изменения count == 2 . Пока я использую цикл

 for (i in 1:length(test$value))
{
  if(isTRUE(is.na(test$count[i]))){
    test$count[i] <- test$count[i-1]
  }
}
 

Однако это занимает вечность! Кто-нибудь может придумать более эффективный способ получить тот же результат, что и цикл? Это мне очень помогло бы! Заранее спасибо!

Ответ №1:

Вы можете использовать fill пакет tidyr, чтобы сделать именно это:

 tidyr::fill(test, count)
#> # A tibble: 100 x 2
#>    value count
#>    <dbl> <int>
#>  1     0     1
#>  2   781     1
#>  3  1109     1
#>  4    57     1
#>  5   250     1
#>  6   541     1
#>  7   533     1
#>  8   320     1
#>  9   322     1
#> 10  1033     1
#> # ... with 90 more rows

 

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

1. О боже gosh…it было так просто: D Большое спасибо!!

Ответ №2:

Вы также можете использовать na.locf() из zoo :

 library(zoo)
#Code
test$count <- na.locf(test$count)
 

Вывод:

 # A tibble: 100 x 2
   value count
   <dbl> <int>
 1     0     1
 2   781     1
 3  1109     1
 4    57     1
 5   250     1
 6   541     1
 7   533     1
 8   320     1
 9   322     1
10  1033     1
# ... with 90 more rows
 

Ответ №3:

Мы также можем использовать

 library(zoo)
transform(test, count = na.locf0(count))
 

Или использовать data.table nafill для эффективной версии

  library(data.table)
 setDT(test)[, count:= nafill(count, type = 'locf')]
 

-выходной сигнал

 test
#      value count
#  1:      0     1
#  2:    781     1
#  3:   1109     1
#  4:     57     1
#  5:    250     1
#  6:    541     1
#  7:    533     1
#  8:    320     1
#  9:    322     1
# 10:   1033     1
# 11:    291     1
# 12:   2213     1
# 13:   1845     1
# 14:    618     1
# ..