Je veux créer un tableau croisé d'une variable avec toutes les autres variables du data.frame.
library(tidyverse) library(janitor) humans <- starwars %>% filter(species == "Human") humans %>% janitor::tabyl(gender, eye_color) gender blue blue-gray brown dark hazel yellow female 3 0 5 0 1 0 male 9 1 12 1 1 2 humans %>% dplyr::select_if(is.character) %>% dplyr::select(-name, -gender) %>% purrr::map(.f = ~janitor::tabyl(dat = humans, gender, .x)) Error: Unknown columns `blond`, `none`, `brown`, `brown, grey`, `brown` and ... Call `rlang::last_error()` to see a backtrace
4 Réponses :
En supposant que nous ayons besoin d'une table par paires avec 'gender'
library(xtable) humans %>% dplyr::select_if(is.character) %>% dplyr::select(-name, -gender) %>% imap(~ tibble(!! .y := .x) %>% mutate(gender = humans[['gender']]) %>% janitor::tabyl(!!rlang::sym(names(.)[1]), gender) %>% mutate(colNname = .y) %>% rename_at(1, ~ 'Variable')) %>% xtableList
La xtable :: xtableList
nécessite que les noms soient identiques les éléments list
. Pour ce faire, changez le nom de la première colonne de la même manière dans les éléments list
, puis créez une colonne d'identifiant
humans %>% dplyr::select_if(is.character) %>% dplyr::select(-name, -gender) %>% imap(~ tibble(!! .y := .x) %>% mutate(gender = humans[['gender']]) %>% janitor::tabyl(!!rlang::sym(names(.)[1]), gender)) #$hair_color # hair_color female male # auburn 1 0 # auburn, grey 0 1 # auburn, white 0 1 # black 1 7 # blond 0 3 # brown 6 8 # brown, grey 0 1 # grey 0 1 # none 0 3 # white 1 1 #$skin_color # skin_color female male # dark 0 4 # fair 3 13 # light 6 5 #...
Merci @akrun pour une réponse très utile. Cependant, impossible de rendre la sortie dans .Rnw
en utilisant xtable :: xtableList
. Des pensées.
@ MYaseen208 Je pense que le problème avec les noms qui ne sont pas courants. Vous pouvez rendre les noms communs et créer une nouvelle colonne comme identifiant, c'est-à-dire humains%>% dplyr :: select_if (is.character)%>% dplyr :: select (-name, -gender)%>% imap ( ~ tibble (!! .y: = .x)%>% mutate (gender = humains [['gender']])%>% concierge :: tabyl (!! rlang :: sym (names (.) [1] ), sexe)%>% mutate (colNname = .y)%>% rename_at (1, ~ 'Variable'))%>% xtableList
En utilisant uniquement data.table
(et un %>%
):
library(data.table) swDT <- data.table(starwars) setkey(swDT, gender, hair_color) swDT[species == "Human" ][CJ(gender, hair_color, unique =TRUE), .N, .EACHI] %>% dcast(hair_color ~ gender, value.var = "N") hair_color female male 1: auburn 1 0 2: auburn, grey 0 1 3: auburn, white 0 1 4: black 1 7 5: blond 0 3 6: brown 6 8 7: brown, grey 0 1 8: grey 0 1 9: none 0 3 10: white 1 1
Les colonnes de liste dans starwars
ajoutent de la complexité, mais voici un exemple avec mtcars
: crosstab cyl
par rapport à toutes les autres variables.
$vs cyl/vs 0 1 4 1 10 6 3 4 8 14 0
Renvoie une liste de tableaux croisés. cyl x am, cyl x carb, etc.:
purrr::map2(.x = ., .y = names(.), ~ janitor::adorn_title(.x, col_name = .y, placement = "combined"))
Si vous voulez continuer à manipuler ces données. cadres, vous pouvez trouver cette option de titre plus conviviale:
$`am` am cyl 0 1 4 3 8 6 4 3 8 12 2 $carb carb cyl 1 2 3 4 6 8 4 5 6 0 0 0 0 6 2 0 0 4 1 0 8 0 4 3 6 0 1 ...
Ce qui vous donne:
mtcars %>% tidyr::gather(var, value, -cyl) %>% janitor::tabyl(cyl, value, var, show_missing_levels = FALSE) %>% purrr::map2(.x = ., .y = names(.), ~ janitor::adorn_title(.x, col_name = .y))
tably
prend les noms comme arguments et vous lui avez transmis un vecteur.
Si vous utilisez imap
vous aurez accès au nom de la colonne, que vous pouvez convertir en symbole, et comme concierge
prend en charge la quasi-citation, vous pouvez write:
cols <- setdiff(names(Filter(is.character,humans)), c("name","gender")) l <- lapply(cols, function(x) { res <- janitor:::tabyl_2way(humans, as.name(x), quote(gender)) names(res)[1] <- "x" res }) xtableList(l)
Fait intéressant, tabyl.data.frame
appelle une fonction non exportée qui fonctionne sur les symboles donc en l'appelant directement, nous pouvons ignorer la suppression des guillemets et utiliser base R.
humans %>% select_if(is.character) %>% select(-name, -gender) %>% imap(.f = ~tabyl(dat = humans, !!sym(.y), gender) %>% rename_at(1,~"x")) %>% xtableList
Pour le faire fonctionner avec la suggestion de xtable
@ akrun fonctionne également ici:
cols <- setdiff(names(Filter(is.character,humans)), c("name","gender")) lapply(cols, function(x) janitor:::tabyl_2way(humans, as.name(x), quote(gender))) # [[1]] # hair_color female male # auburn 1 0 # auburn, grey 0 1 # auburn, white 0 1 # black 1 7 # blond 0 3 # brown 6 8 # brown, grey 0 1 # grey 0 1 # none 0 3 # white 1 1 # # [[2]] # skin_color female male # dark 0 4
Merci @Moody_Mudskipper pour votre réponse. Cependant, toujours pas en mesure de rendre la sortie en .Rnw en utilisant xtable en tant qu'êtres humains%>% select_if (is.character)%>% select (-name, -gender)%>% imap (.f = ~ janitor :: tabyl ( dat = humains, !! sym (.y), gender))%>% xtableList