2 votes

Comment faire passer les instructions if dans R

J'ai des données provenant de mes comptes Facebook, Twitter, Instagram, Youtube et LinkedIn que j'aimerais analyser. Je dispose d'un cadre de données similaire au suivant :

df <- data.frame(tw_likes = c(5,4,6,NA,NA,NA,NA,NA,NA), 
                 tw_comments = c(3,5,NA,NA,NA,NA,NA,NA,NA), 
                 fb_likes = c(NA,NA,NA,7,4,8,NA,NA,NA), 
                 fb_comments = c(NA,NA,NA,NA,NA,7,NA,NA,NA), 
                 ig_likes = c(NA,NA,NA,NA,NA,NA,NA,NA,5), 
                 ig_comments = c(NA,NA,NA,NA,NA,NA,43,4,2))

ce que je veux faire, c'est créer une colonne supplémentaire Platform qui prendra les valeurs "Twitter", "Facebook" ou "Instagram" en fonction de la base de données ci-dessus.

Ma tactique a été la suivante :

for(i in 1:nrow(df){
     if(!is.na(df$tw_likes[i]) | !is.na(df$tw_comments[i])){
          df$Platform[i] <- "Twitter"
     }
     else if(!is.na(df$fb_likes[i]) | !is.na(df$fb_comments[i])){
          df$Platform[i] <- "Facebook"
     }
     else if(!is.na(df$ig_likes[i]) | !is.na(df$ig_comments[i])){
          df$Platform[i] <- "Instagram"
     }
}

Cela fonctionne, mais la lecture devient plus compliquée. En réalité, j'ai plus de colonnes et plus de plateformes de médias sociaux à gérer, alors y a-t-il un moyen de canaliser les données pour que je n'aie pas à écrire df$ autant de fois ?

J'ai également pensé que si je ne pouvais pas retirer le df$ je pourrais combiner les !is.na() doit être un énoncé par énoncé if ?

4voto

Fino Points 1344

Voici une option avec dplyr 's case_when()

df %>% 
  mutate(Plataform = case_when(
    !is.na(tw_likes) | !is.na(tw_comments) ~ "Twitter",
    !is.na(fb_likes) | !is.na(fb_comments) ~ "Facebook",
    !is.na(ig_likes) | !is.na(ig_comments) ~ "Instagram"))

4voto

akrun Points 148302

Voici une façon de procéder base R pour diviser l'ensemble de données en un list de colonnes ayant le même préfixe (en supprimant la chaîne de caractères du suffixe des noms de colonnes), effectuer un rowSums pour créer un matrix , poser sa candidature max.col pour obtenir la position de la colonne pour chaque ligne et modifier cet index en passant un vecteur de valeurs de remplacement dans le même ordre que les noms des colonnes scindées

i1 <- max.col(sapply(split.default(df, sub("_.*", "", names(df))),
        function(x) rowSums(!is.na(x)) > 0 ), 'first')
df$Platform <- c("Facebook", "Instagram", "Twitter")[i1]
df$Platform
#[1] "Twitter"   "Twitter"   "Twitter"   "Facebook"  "Facebook"  
#[6]   "Facebook"  "Instagram" "Instagram" "Instagram"

2voto

Jon Spring Points 4096

Voici une autre approche utilisant dplyr y tidyr pour extraire les données en format long, filtrer les blancs et ajouter le nom le plus long sur la base d'une table de recherche :

library(tidyr); library(dplyr)
df %>%
  pivot_longer(cols = everything(), 
               names_to = c("pltfm", "stat"),
               names_sep = "_",
               values_to = "value") %>%
  filter(!is.na(value)) %>%
  left_join(
    tibble(pltfm = c("tw", "fb", "ig"),
           Platform = c("Twitter", "Facebook", "Instagram"))
  )

#Joining, by = "pltfm"
## A tibble: 13 x 4
#   pltfm stat     value Platform 
#   <chr> <chr>    <dbl> <chr>    
# 1 tw    likes        5 Twitter  
# 2 tw    comments     3 Twitter  
# 3 tw    likes        4 Twitter  
# 4 tw    comments     5 Twitter  
# 5 tw    likes        6 Twitter  
# 6 fb    likes        7 Facebook 
# 7 fb    likes        4 Facebook 
# 8 fb    likes        8 Facebook 
# 9 fb    comments     7 Facebook 
#10 ig    comments    43 Instagram
#11 ig    comments     4 Instagram
#12 ig    likes        5 Instagram
#13 ig    comments     2 Instagram

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