Установите значение равным нулю, если условие выполняется для каждого столбца отдельно

#r #data.table

Вопрос:

Если есть запись >= 10, я пытаюсь установить все остальные значения для этого идентификатора равными нулю для этого конкретного года в таблице данных. Все значения остаются неизменными, если нет значения больше или равного 10. Если существует более одного значения больше 10, следует сохранить только самую большую запись.

Здесь у меня есть пример таблицы данных:

 library(data.table)

data = data.table(
  ID = c("a1", "a2", "a2", "a1", "a2", "a1", "a1"),
  "2018" = c(3,5,11,3,9,22,6),
  "2019" = c(3,5,6,21,1,4,0),
  "2020" = c(0,4,13,9,16,7,9),
  "2021" = c(4,0,3,8,5,4,6))
 

Я попробовал сделать это с помощью цикла for, но я не смог сделать это с двумя измерениями.
Желаемый результат будет выглядеть так:

 solution <- data.table(
  ID = c("a1", "a2", "a2", "a1", "a2", "a1", "a1"),
  "2018" = c(0,0,11,0,0,22,0),
  "2019" = c(0,5,6,21,1,0,0),
  "2020" = c(0,0,0,9,16,7,9),
  "2021" = c(4,0,3,8,5,4,6))
 

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

1. Сгруппированы ли они по «идентификатору»

2. Нет, не нужно, большое спасибо за ваш ответ:)

Ответ №1:

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

 library(data.table)
nm1 <- names(data)[-1]
data[, (nm1) := lapply(.SD, function(x) if(any(x >= 10)) 
       replace(x, x != max(x), 0) else x), ID]
 

-выход

 > data
   ID 2018 2019 2020 2021
1: a1    0    0    0    4
2: a2    0    5    0    0
3: a2   11    6    0    3
4: a1    0   21    9    8
5: a2    0    1   16    5
6: a1   22    0    7    4
7: a1    0    0    9    6
 

Ответ №2:

Если вы можете принять решение с tibble помощью вместо data.table ,

 library(tidyverse)

data = tibble(
  ID = c("a1", "a2", "a2", "a1", "a2", "a1", "a1"),
  "2018" = c(3,5,11,3,9,22,6),
  "2019" = c(3,5,6,21,1,4,0),
  "2020" = c(0,4,13,9,16,7,9),
  "2021" = c(4,0,3,8,5,4,6))

data %>% 
  mutate(row_id = 1:n()) %>%
  pivot_longer(-c(row_id, ID), names_to = "year") %>%
  group_by(year, ID) %>%
  mutate(
    value = if (any(value >= 10)) {
      if_else(1:length(value) == which.max(value), value, 0)
    } else {
      value
    }) %>%
  ungroup() %>%
  pivot_wider(names_from = year)
#> # A tibble: 7 x 6
#>   ID    row_id `2018` `2019` `2020` `2021`
#>   <chr>  <int>  <dbl>  <dbl>  <dbl>  <dbl>
#> 1 a1         1      0      0      0      4
#> 2 a2         2      0      5      0      0
#> 3 a2         3     11      6      0      3
#> 4 a1         4      0     21      9      8
#> 5 a2         5      0      1     16      5
#> 6 a1         6     22      0      7      4
#> 7 a1         7      0      0      9      6
 

Создано 2021-08-19 пакетом reprex (v1.0.0)

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

1. Большое спасибо, в моем случае data.table работает лучше