1
votes

Sous-ensemble de trames de données sous plusieurs conditions

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,


0 commentaires

4 Réponses :


0
votes

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


0 commentaires

1
votes

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)))


0 commentaires

1
votes

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


0 commentaires

1
votes

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


0 commentaires