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