2 votes

Comment combiner la fonction across () avec mutate () et case_when () pour modifier les valeurs de plusieurs colonnes en fonction d'une condition ?

J'ai un ensemble de données démographiques, qui comprend l'âge des personnes dans un ménage. Ces données sont recueillies par le biais d'une enquête et les participants sont autorisés à refuser de fournir leur âge.

Le résultat est un ensemble de données avec un ménage par ligne (chacun avec un code d'identification du ménage), et diverses caractéristiques du ménage telles que l'âge dans les colonnes. Les réponses refusées sont codées comme "R", et vous pouvez recréer un échantillon en utilisant le code ci-dessous :

df <- list(Household_ID = c("1A", "1B", "1C", "1D", "1E"),
           AGE1 = c("25", "47", "39", "50", "R"),
           AGE2 = c("66", "23", "71", "R", "16"),
           AGE3 = c("28", "17", "R", "R", "80"),
           AGE4 = c("81", "22", "48", "59", "R"))

df <- as_tibble(df)

> df
# A tibble: 5 x 5
  Household_ID AGE1  AGE2  AGE3  AGE4 
  <chr>        <chr> <chr> <chr> <chr>
1 1A           25    66    28    81   
2 1B           47    23    17    22   
3 1C           39    71    R     48   
4 1D           50    R     R     59   
5 1E           R     16    80    R 

Pour ce qui nous concerne, nous recodons le "R" en "-9" afin de pouvoir ensuite convertir le format des colonnes AGE en entier, et effectuer l'analyse. Nous faisons généralement cela dans un autre logiciel et mon objectif est de reproduire ce processus dans R.

J'ai réussi à le faire avec le code suivant :

df <- df %>% mutate(AGE1 = case_when(AGE1 == "R" ~ "-9", TRUE ~ as.character(AGE1)))
df <- df %>% mutate(AGE2 = case_when(AGE2 == "R" ~ "-9", TRUE ~ as.character(AGE2)))
df <- df %>% mutate(AGE3 = case_when(AGE3 == "R" ~ "-9", TRUE ~ as.character(AGE3)))
df <- df %>% mutate(AGE4 = case_when(AGE4 == "R" ~ "-9", TRUE ~ as.character(AGE4)))

Étant donné que cela semble maladroit, j'ai essayé de trouver une solution en utilisant mutate_if etc. mais j'ai lu que ceux-ci ont été remplacés par across(). J'ai donc essayé de reproduire cette opération en utilisant across() :

df <- df %>%
  mutate(across(AGE1:AEG4),
          ~ (case_when(. == "R" ~ "-9")))

Mais je reçois l'erreur suivante :

Error: Problem with `mutate()` input `..2`.
x Input `..2` must be a vector, not a `formula` object.
i Input `..2` is `~(case_when(. == "R" ~ "-9"))`.

Cela fait un moment que je me débats avec cette question et que je cherche sur Internet, mais je n'arrive pas à comprendre ce qui me manque. J'apprécierais vraiment que vous m'expliquiez comment faire pour que cela fonctionne, s'il vous plaît et merci.

EDIT : Résolu !

df <- df %>%
  mutate(across(AGE1:AGE4, ~ (case_when(.x == "R" ~ "-9", TRUE ~ as.character(.x)))))

2voto

AnilGoyal Points 16753

Pourquoi pas tout simplement ?

df[,2:5][df[, 2:5] == 'R'] <- '-9'

# A tibble: 5 x 5
  Household_ID AGE1  AGE2  AGE3  AGE4 
  <chr>        <chr> <chr> <chr> <chr>
1 1A           25    66    28    81   
2 1B           47    23    17    22   
3 1C           39    71    -9    48   
4 1D           50    -9    -9    59   
5 1E           -9    16    80    -9

2voto

Anoushiravan R Points 4928

Ou peut-être celle-ci qui n'est pas très différente de l'interprétation de ce cher @TarJae :

library(dplyr)
library(stringr)

df %>%
  mutate(across(AGE1:AGE4, ~ str_replace(., "R", "-9")),
         across(AGE1:AGE4, as.integer))

# A tibble: 5 x 5
  Household_ID  AGE1  AGE2  AGE3  AGE4
  <chr>        <int> <int> <int> <int>
1 1A              25    66    28    81
2 1B              47    23    17    22
3 1C              39    71    -9    48
4 1D              50    -9    -9    59
5 1E              -9    16    80    -9

Données :

df <- list(Household_ID = c("1A", "1B", "1C", "1D", "1E"),
           AGE1 = c("25", "47", "39", "50", "R"),
           AGE2 = c("66", "23", "71", "R", "16"),
           AGE3 = c("28", "17", "R", "R", "80"),
           AGE4 = c("81", "22", "48", "59", "R"))

df <- as_tibble(df)

1voto

TarJae Points 9674

Vous pourriez utiliser across con replace .

  1. Liste à débattre as_tibble()
  2. remplacer R par -9
  3. classe entière pour AGE

    df %>% as_tibble() %>% mutate(across(everything(), ~replace(., . == "R" , "-9"))) %>% type.convert(as.is=TRUE)

Sortie :

  Household_ID  AGE1  AGE2  AGE3  AGE4
  <chr>        <int> <int> <int> <int>
1 1A              25    66    28    81
2 1B              47    23    17    22
3 1C              39    71    -9    48
4 1D              50    -9    -9    59
5 1E              -9    16    80    -9

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X