1
votes

R mutate_at sur un sous-ensemble de lignes

Ma question est similaire à ce post ( Application conditionnelle de mutate_at à des lignes spécifiques dans un dataframe dans R ), et j'ai pu reproduire le résultat. Mais si j'ai essayé d'appliquer cela à mon problème, qui met entre parenthèses la valeur de la cellule pour les lignes et colonnes sélectionnées, je rencontre des messages d'erreur. Voici un exemple reproductible.

require(tidyverse)
> df %>%   mutate(dat1 = ifelse(name == "t_stat", paste0("(", dat1, ")"), dat1),
+                 dat2 = ifelse(name == "t_stat", paste0("(", dat2, ")"), dat1),
+                 dat3 = ifelse(name == "t_stat", paste0("(", dat3, ")"), dat1))
# A tibble: 10 x 5
   dep   name     dat1     dat2      dat3    
   <chr> <chr>    <chr>    <chr>     <chr>   
 1 cyl   estimate 1.151    1.151     1.151   
 2 cyl   t_stat   (6.686)  (8.423)   (5.191) 
 3 disp  estimate 102.902  102.902   102.902 
 4 disp  t_stat   (12.107) (12.148)  (7.79)  
 5 drat  estimate -0.422   -0.422    -0.422  
 6 drat  t_stat   (-5.237) (-5.304)  (-2.629)
 7 hp    estimate 37.576   37.576    37.576  
 8 hp    t_stat   (5.067)  (6.172)   (4.842) 
 9 mpg   estimate -5.057   -5.057    -5.057  
10 mpg   t_stat   (-8.185) (-10.622) (-7.91)

Étant donné le cadre de données ci-dessus, j'espère mettre entre parenthèses les valeurs de cellule de la colonne dat1 , dat2 et dat3 lorsque name == t_stat . Voici ce que j'ai essayé, mais il semble que paste0 ne soit pas accepté dans la fonction case_when dans ce cas.

require(tidyverse)
df %>% mutate_at(vars(matches("dat")), 
+                  funs( case_when(name == 't_stat' ~ paste0("(", ., ")"), TRUE ~ .) )) 
Error: must be a character vector, not a double vector


0 commentaires

3 Réponses :


1
votes

Fondamentalement, vous devez d'abord convertir dbl en char , et c'est ce que le message d'erreur dit également Erreur: doit être un vecteur de caractères, pas un double vecteur

Comme @Rohan l'a dit à juste titre, case_when est de type strict ce qui signifie qu'il s'attend à ce que la sortie soit de la même classe.

# A tibble: 10 x 5
   dep   name     dat1     dat2      dat3    
   <chr> <chr>    <chr>    <chr>     <chr>   
 1 cyl   estimate 1.151    1.274     1.078   
 2 cyl   t_stat   (6.686)  (8.423)   (5.191) 
 3 disp  estimate 102.902  106.429   103.687 
 4 disp  t_stat   (12.107) (12.148)  (7.79)  
 5 drat  estimate -0.422   -0.394    -0.194  
 6 drat  t_stat   (-5.237) (-5.304)  (-2.629)
 7 hp    estimate 37.576   38.643    36.777  
 8 hp    t_stat   (5.067)  (6.172)   (4.842) 
 9 mpg   estimate -5.057   -4.843    -4.539  
10 mpg   t_stat   (-8.185) (-10.622) (-7.91) 

Sortie sous la forme

df %>% mutate_at(vars(matches("dat")),
                 ~case_when(name =='t_stat'~ paste0("(",as.character(.x),")"),
                            T ~ as.character(.x))
                 )


0 commentaires

1
votes

Le message d'erreur est ... inutile.

Votre problème est que vous mélangez des données numériques et de caractères dans une colonne. Les variables dat sont numériques.

df %>% mutate_at(vars(matches("dat")), 
                 funs( case_when(name == 't_stat' ~ paste0("(", ., ")"),
                                 TRUE ~ as.character(.))))

# A tibble: 10 x 5
   dep   name     dat1     dat2      dat3    
   <chr> <chr>    <chr>    <chr>     <chr>   
 1 cyl   estimate 1.151    1.274     1.078   
 2 cyl   t_stat   (6.686)  (8.423)   (5.191) 
 3 disp  estimate 102.902  106.429   103.687 
 4 disp  t_stat   (12.107) (12.148)  (7.79)  
 5 drat  estimate -0.422   -0.394    -0.194  
 6 drat  t_stat   (-5.237) (-5.304)  (-2.629)
 7 hp    estimate 37.576   38.643    36.777  
 8 hp    t_stat   (5.067)  (6.172)   (4.842) 
 9 mpg   estimate -5.057   -4.843    -4.539  
10 mpg   t_stat   (-8.185) (-10.622) (-7.91) 


0 commentaires

1
votes

case_when est de type strict, ce qui signifie qu'il s'attend à ce que la sortie soit de la même classe. Vos colonnes d'origine sont de type numérique alors qu'en ajoutant "(" autour de vos données, vous en faites un caractère de classe.

De plus, funs est depuis longtemps obsolète et mutate_at sera bientôt remplacé par across .

library(dplyr)
df %>% 
    mutate_at(vars(matches("dat")), 
      ~case_when(name == 't_stat' ~ paste0("(", ., ")"), TRUE ~ as.character(.)))


0 commentaires