¿Cómo comparar valores dentro del subgrupo?

Tengo porcentajes de votos para dos candidatos para varios distritos. Me gustaría ver si los porcentajes de votos son muy cercanos, donde defino muy cerca como una diferencia del 0,5%. El objetivo es conseguir una nueva columna booleana que produzca TRUE si el porcentaje de voto era cercano en ese distrito y FALSE si el porcentaje de voto no era cercano.

MWE:

set.seed(1)
district <- rep(letters[1:5], each = 2)
candidate <- rep(LETTERS[1:2], 5)
vote_pct <- round(rnorm(10, 0.5, 0.01), 3)
my_df <- as.data.frame(cbind(district, candidate, vote_pct))

Así los datos parecen:

> my_df
   district candidate vote_pct
1         a         A    0.494
2         a         B    0.502
3         b         A    0.492
4         b         B    0.516
5         c         A    0.503
6         c         B    0.492
7         d         A    0.505
8         d         B    0.507
9         e         A    0.506
10        e         B    0.497

En mi conjunto de datos, los porcentajes de dos candidatos en un distrito no superarían el 100%.

Lo que me gustaría es

   district candidate vote_pct close
1         a         A    0.494 FALSE
2         a         B    0.502 FALSE
3         b         A    0.492 FALSE
4         b         B    0.516 FALSE
5         c         A    0.503 FALSE
6         c         B    0.492 FALSE
7         d         A    0.505 TRUE
8         d         B    0.507 TRUE
9         e         A    0.506 FALSE
10        e         B    0.497 FALSE

O alternativamente,

   district vote_diff close
1         a    -0.008 FALSE
...

En mi conjunto de datos, hay muchas más columnas en caso de que haga una diferencia.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por scriptsculptor52b5


4 Respuestas:

  • Usted puede calcular la diferencia absoluta entre los dos candidatos y asignar TRUE si es menos de 0.005.

    library(dplyr)
    
    my_df %>%
      group_by(district) %>%
      mutate(close = abs(diff(as.numeric(vote_pct))) < 0.005)
    
    #   district candidate vote_pct close
    #                
    # 1 a        A         0.494    FALSE
    # 2 a        B         0.502    FALSE
    # 3 b        A         0.492    FALSE
    # 4 b        B         0.516    FALSE
    # 5 c        A         0.503    FALSE
    # 6 c        B         0.492    FALSE
    # 7 d        A         0.505    TRUE 
    # 8 d        B         0.507    TRUE 
    # 9 e        A         0.506    FALSE
    #10 e        B         0.497    FALSE
    

    El segundo producto previsto podría lograrse mediante:

    my_df %>%
      group_by(district) %>%
      summarise(vote_diff = abs(diff(as.numeric(vote_pct))), 
                close = vote_diff < 0.005)
    
    # district vote_diff close
    #           
    #1 a            0.008 FALSE
    #2 b            0.024 FALSE
    #3 c            0.011 FALSE
    #4 d            0.002 TRUE 
    #5 e            0.009 FALSE
    

    Respondida el Dec 17, 2020 a las 08:36 - por devninjax

    Votos positivos: 0 | Votos negativos: 0

  • Esto funciona:

    library(dplyr)
    df %>% group_by(district) %>% 
       mutate(close = case_when(vote_pct[candidate == 'A'] >= 0.5 & vote_pct[candidate == 'B'] >=0.5 ~  TRUE,TRUE  ~ FALSE ))
    # A tibble: 10 x 4
    # Groups:   district [5]
       district candidate vote_pct close
                    
     1 a        A            0.494 FALSE
     2 a        B            0.502 FALSE
     3 b        A            0.492 FALSE
     4 b        B            0.516 FALSE
     5 c        A            0.503 FALSE
     6 c        B            0.492 FALSE
     7 d        A            0.505 TRUE 
     8 d        B            0.507 TRUE 
     9 e        A            0.506 FALSE
    10 e        B            0.497 FALSE
    

    Respondida el Dec 17, 2020 a las 08:41 - por byteninja

    Votos positivos: 0 | Votos negativos: 0

  • Para lograr obtener una nueva columna que indique si la diferencia de porcentaje de voto entre los dos candidatos es menor o igual a 0.5%, puedes utilizar el siguiente código en R:

    R
    library(dplyr)
    
    set.seed(1)
    district <- rep(letters[1:5], each = 2)
    candidate <- rep(LETTERS[1:2], 5)
    vote_pct <- round(rnorm(10, 0.5, 0.01), 3)
    my_df <- as.data.frame(cbind(district, candidate, vote_pct))
    
    my_df <- my_df %>%
      group_by(district) %>%
      mutate(vote_diff = abs(diff(vote_pct)),
             close = vote_diff <= 0.005)
    
    print(my_df)
    

    En este código, usamos la función mutate de la librería dplyr para crear dos nuevas columnas: vote_diff, que contiene la diferencia absoluta entre los dos porcentajes de voto de cada distrito, y close, que es una columna booleana que indica si la diferencia de porcentaje de voto es menor o igual a 0.5%.

    Al agrupar por district con group_by, aseguramos que se realice la comparación dentro de cada subgrupo de distritos.

    El resultado será un dataframe que incluye las columnas originales junto con las columnas nuevas vote_diff y close que indican si los porcentajes de voto son cercanos en cada distrito.

    Respondida el Dec 18, 2020 a las 08:37 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Usando la función abs() y ifelse():

    
    my_df$close <- ifelse(abs(my_df$vote_pct - 0.5) <= 0.005, TRUE, FALSE)
    

    Usando la función near() del paquete dplyr:

    
    library(dplyr)
    my_df <- my_df %>%
      mutate(close = near(vote_pct, 0.5, tol = 0.005))
    

    Usando la función within() del paquete plyr:

    
    library(plyr)
    my_df$close <- within(my_df, close <- abs(vote_pct - 0.5) <= 0.005)
    

    Calculando la diferencia de votos y comparándola con 0,005:

    
    my_df$vote_diff <- my_df$vote_pct - 0.5
    my_df$close <- abs(my_df$vote_diff) <= 0.005
    

    Cualquiera de estas soluciones agregará una nueva columna booleana llamada "close" a tu marco de datos, que indica si la diferencia de porcentajes de votos es menor o igual a 0,005.

    Respondida el Dec 18, 2020 a las 08:51 - por Gemini

    Votos positivos: 0 | Votos negativos: 0