J'ai une base de données contenant des informations sur les deux premiers candidats aux élections locales au Brésil qui ressemble à ceci:
Municipality Win Margin A 2 B 10
Je souhaite conserver dans mes données uniquement les informations sur les municipalités où race est un homme contre une femme.
Donc, je recherche une sortie comme celle-ci:
Name Municipality Gender Vote_Share Andressa A F 51 Marcos A M 49 Anderson B M 55 Cibelle B F 45
De plus, je veux créer un autre objet contenant la marge de victoire pour les femmes (part des voix pour les femmes - part des voix pour les hommes) aux élections de chaque municipalité:
Name <- c('Andressa', 'Marcos', 'Anderson', 'Cibelle', 'Ivy', 'Eliana') Municipality <- c('A', 'A', 'B', 'B', 'C', 'C') Gender <- c('F', 'M', 'M', 'F', 'F', 'F') Vote_Share <- c(51, 49, 55, 45, 70, 30) data <- data.frame(Name, Municipality, Gender, Vote_Share) Name Municipality Gender Vote_Share Andressa A F 51 Marcos A M 49 Anderson B M 55 Cibelle B F 45 Ivy C F 70 Eliana C F 30
Cordialement,
4 Réponses :
Nous pouvons regrouper par 'Municipalité' et filtrer
les groupes ayant deux valeurs 'Genre' distinctes
subset(data, Municipality %in% names(which(rowSums(table(Municipality, Gender) > 0) > 1))) # Name Municipality Gender Vote_Share #1 Andressa A F 51 #2 Marcos A M 49 #3 Anderson B M 55 #4 Cibelle B F 45
Ou spécifier que les deux 'niveaux' sont dans le ' Genre '
library(data.table) setDT(data)[, .SD[uniqueN(Gender) == 2)], .(Municipality) ][, .(WinMargin = abs(diff(Vote_Share))), by = Municipality]
Une fois que nous obtenons la première sortie résumée
out1 %>% summarise(WinMargin = abs(diff(Vote_Share))) # A tibble: 2 x 2 # Municipality WinMargin # <fct> <dbl> #1 A 2 #2 B 10
Avec les données .table
, on peut faire
data %>% group_by(Municipality) %>% filter(all(c("M", "F") %in% Gender))
Ou en base R
, on peut utiliser subset code> avec
table
library(dplyr) out1 <- data %>% group_by(Municipality) %>% filter(n_distinct(Gender) == 2) out1 # A tibble: 4 x 4 # Groups: Municipality [2] # Name Municipality Gender Vote_Share # <fct> <fct> <fct> <dbl> #1 Andressa A F 51 #2 Marcos A M 49 #3 Anderson B M 55 #4 Cibelle B F 45
Voici une solution de base R, utilisant subset ()
+ ave()
> dfout Name Municipality Gender Vote_Share 1 Andressa A F 51 2 Marcos A M 49 3 Anderson B M 55 4 Cibelle B F 45
ou
dfout <- subset(df,as.logical(ave(Gender,Municipality,FUN = function(x) !any(duplicated(x)))))
tel que
dfout <- subset(df,as.logical(ave(Gender,Municipality,FUN = function(x) length(unique(x))==2)))
Vous pouvez factoriser
ize puis as.numeric
, prendre la moyenne
et exclure là où elle n'est pas 1
.
dat <- structure(list(Name = structure(c(2L, 6L, 1L, 3L, 5L, 4L), .Label = c("Anderson", "Andressa", "Cibelle", "Eliana", "Ivy", "Marcos"), class = "factor"), Municipality = structure(c(1L, 1L, 2L, 2L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), Gender = structure(c(1L, 2L, 2L, 1L, 1L, 1L), .Label = c("F", "M"), class = "factor"), Vote_Share = c(51, 49, 55, 45, 70, 30)), class = "data.frame", row.names = c(NA, -6L))
Curieusement, cela fonctionne aussi, car F
est un raccourci de FALSE
et F
avec M
n'a aucun sens -> NA
, que nous pouvons exclure.
dat[is.na(with(dat, ave(as.logical(Gender), Municipality))), ] # Name Municipality Gender Vote_Share # 1 Andressa A F 51 # 2 Marcos A M 49 # 3 Anderson B M 55 # 4 Cibelle B F 45
Données: em>
dat[with(dat, ave(as.numeric(as.factor(Gender)), Municipality)) != 1, ] # Name Municipality Gender Vote_Share # 1 Andressa A F 51 # 2 Marcos A M 49 # 3 Anderson B M 55 # 4 Cibelle B F 45
Une autre façon avec ave
et sous-ensemble
dans la base R
aggregate(Vote_Share~Municipality, temp, function(x) diff(range(x))) # Municipality Vote_Share #1 A 2 #2 B 10
puis utilisez agrégat
pour calculer la différence de vote.
temp <- subset(data, as.logical(ave(Gender, Municipality, FUN = function(x) all(c('F', 'M') %in% x)))) # Name Municipality Gender Vote_Share #1 Andressa A F 51 #2 Marcos A M 49 #3 Anderson B M 55 #4 Cibelle B F 45