Измените значения ближайших столбцов в каждой строке с помощью цикла for.Ищет другие "более безопасные" решения - PullRequest
0 голосов
/ 15 сентября 2018

Допустим, у меня есть фрейм данных mtcar

head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1

В каждой строке для каждого 5-го столбца, начиная со столбца 2, я хочу оценить значение и изменить 4 ближайших столбца на «NA», если ониверны, иначе ничего не делают.Когда mtcars

mtcars[2,2]="NA"

mtcars[3,7]=3

t<-(ncol(mtcars)-1)/5
for (i in 1:nrow(mtcars)){
  for (j in 1:t){
    if (mtcars[i,((j-1)*5+2)]<3.01)  {
      mtcars[i,((j-1)*5+3):((j-1)*5+6)]="NA"
    } else if (mtcars[i,((j-1)*5+2)]=="NA"){
      mtcars[i,((j-1)*5+3):((j-1)*5+6)]="NA"
    }
  }
}

, он работает как хотел.

mtcars
                   mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6   160 110  3.9  2.62 16.46  0  1    4    4
Mazda RX4 Wag       21.0  NA    NA  NA   NA    NA 17.02  0  1    4    4
Datsun 710          22.8   4   108  93 3.85  2.32  3.00 NA NA   NA   NA
Hornet 4 Drive      21.4   6   258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8   360 175 3.15  3.44 17.02  0  0    3    2
Valiant             18.1   6   225 105 2.76  3.46 20.22  1  0    3    1
Duster 360          14.3   8   360 245 3.21  3.57 15.84  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69  3.19 20.00  1  0    4    2
Merc 230            22.8   4 140.8  95 3.92  3.15 22.90  1  0    4    2

, но когда

mtcars[8,7]="NA"

mtcars

                    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6   160 110  3.9  2.62 16.46 NA NA   NA   NA
Mazda RX4 Wag       21.0  NA    NA  NA   NA    NA 17.02 NA NA   NA   NA
Datsun 710          22.8   4   108  93 3.85  2.32     3 NA NA   NA   NA
Hornet 4 Drive      21.4   6   258 110 3.08 3.215 19.44 NA NA   NA   NA
Hornet Sportabout   18.7   8   360 175 3.15  3.44 17.02 NA NA   NA   NA
Valiant             18.1   6   225 105 2.76  3.46 20.22 NA NA   NA   NA
Duster 360          14.3   8   360 245 3.21  3.57 15.84 NA NA   NA   NA
Merc 240D           24.4   4 146.7  62 3.69  3.19    NA NA NA   NA   NA
Merc 230            22.8   4 140.8  95 3.92  3.15  22.9 NA NA   NA   NA

, тогда все столбцы изменяются на "NA", что не требуется.Я был бы очень признателен за любую помощь, чтобы изменить цикл for или создать новую функцию, которая изменяет только КОЛОННЫ в нужной строке, но не изменяет NA во всех строках.

1 Ответ

0 голосов
/ 16 сентября 2018

Я не был уверен, как исправить логику вашего цикла, поэтому я попытался найти решение, которое дало ожидаемый результат.

Сначала я преобразовал в форму "long" / "tidy" (котораятребуется немного дополнительной работы для mtcars).

library(tidyverse)
mtcars_tidy <- mtcars_mod %>%
  rownames_to_column("model") %>% 
  gather(stat, value, -model) %>%
  mutate_at(vars(model:stat), forcats::as_factor) %>%  # as_factor to preserve order
  # BTW, the character "NA"s aren't numeric, so convert to missing value NA's 
  mutate(value = value %>% as.numeric()) %>%
  arrange(model) %>%
  group_by(model) %>% mutate(col_num = row_number()) %>% ungroup()

head(mtcars_tidy, 14)

Теперь я добавляю NA, используя ваши правила.Чтобы убедиться, что это работает, сначала я отмечаю строки, которые должны сработать после NA.Затем в каждой группе я заменяю значения для следующих четырех записей.Я уверен, что есть более сжатые и быстрые способы сделать это, но я хотел, чтобы процесс был понятен.

mtcars_NA_applied <- mtcars_tidy %>%
  # Test looks for values under 3.01 or missing (NA), only in certain rows
  mutate(test = (value < 3.01 | is.na(value)) & col_num %% 5 == 2) %>%

  # Now we change the next four values. I'm sure there's a more elegant way!
  group_by(model) %>%
  mutate(value = case_when(lag(test,1) ~  NA_real_,
                           lag(test,2) ~  NA_real_,
                           lag(test,3) ~  NA_real_,
                           lag(test,4) ~  NA_real_,
                           TRUE        ~  value)) %>%
  ungroup() %>%

  # Now remove the helper columns and make the table wide again
  select(-col_num, -test) %>%
  spread(stat, value) 

Кажется, что работает.

    > head(mtcars_NA_applied, 8)
# A tibble: 8 x 12
  model               mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
  <fct>             <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Mazda RX4          21       6  160    110  3.9   2.62  16.5     0     1     4     4
2 Mazda RX4 Wag      21      NA   NA     NA NA    NA     17.0     0     1     4     4
3 Datsun 710         22.8     4  108     93  3.85  2.32   3      NA    NA    NA    NA
4 Hornet 4 Drive     21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
5 Hornet Sportabout  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
6 Valiant            18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
7 Duster 360         14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
8 Merc 240D          24.4     4  147.    62  3.69  3.19  NA      NA    NA    NA    NA

Примерданные

mtcars_mod<- mtcars
mtcars_mod[2,2]="NA";   
mtcars_mod[3,7]=3; 
mtcars_mod[8,7]="NA"
mtcars_mod 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...