Home > Blockchain >  Mutate a subset of rows, but keep all rows with dplyr
Mutate a subset of rows, but keep all rows with dplyr

Time:04-18

How can I multiply the population column with -1, for the gender "kvinnor" only, using dplyr?

Here's the code for multiplying all values in population column:

df %>% 
  mutate(neg_kv = population*-1)
# data
df <- tibble::tribble(
     ~region, ~marriage_status, ~age,   ~gender, ~population, ~year,
     "Riket",         "ogifta",   15,     "män",       56031,  1968,
     "Riket",         "ogifta",   15, "kvinnor",       52959,  1968,
     "Riket",         "ogifta",   16,     "män",       55917,  1968,
     "Riket",         "ogifta",   16, "kvinnor",       52979,  1968,
     "Riket",         "ogifta",   17,     "män",       55922,  1968,
     "Riket",         "ogifta",   17, "kvinnor",       52050,  1968,
     "Riket",         "ogifta",   18,     "män",       58681,  1968,
     "Riket",         "ogifta",   18, "kvinnor",       51862,  1968,
     "Riket",         "ogifta",   19,     "män",       60387,  1968,
     "Riket",         "ogifta",   19, "kvinnor",       49750,  1968,
     "Riket",         "ogifta",   20,     "män",       62487,  1968,
     "Riket",         "ogifta",   20, "kvinnor",       50089,  1968,
     "Riket",         "ogifta",   21,     "män",       60714,  1968,
     "Riket",         "ogifta",   21, "kvinnor",       43413,  1968,
     "Riket",         "ogifta",   22,     "män",       56801,  1968,
     "Riket",         "ogifta",   22, "kvinnor",       36301,  1968,
     "Riket",         "ogifta",   23,     "män",       49862,  1968,
     "Riket",         "ogifta",   23, "kvinnor",       29227,  1968,
     "Riket",         "ogifta",   24,     "män",       42143,  1968,
     "Riket",         "ogifta",   24, "kvinnor",       23155,  1968
     )

CodePudding user response:

You need an ifelse statement to identify gender == kvinnor.

library(dplyr)

df %>% mutate(neg_kv = ifelse(gender == "kvinnor", -1 * population, population))

# A tibble: 20 × 7
   region marriage_status   age gender  population  year neg_kv
   <chr>  <chr>           <dbl> <chr>        <dbl> <dbl>  <dbl>
 1 Riket  ogifta             15 män          56031  1968  56031
 2 Riket  ogifta             15 kvinnor      52959  1968 -52959
 3 Riket  ogifta             16 män          55917  1968  55917
 4 Riket  ogifta             16 kvinnor      52979  1968 -52979
 5 Riket  ogifta             17 män          55922  1968  55922
 6 Riket  ogifta             17 kvinnor      52050  1968 -52050
 7 Riket  ogifta             18 män          58681  1968  58681
 8 Riket  ogifta             18 kvinnor      51862  1968 -51862
 9 Riket  ogifta             19 män          60387  1968  60387
10 Riket  ogifta             19 kvinnor      49750  1968 -49750
11 Riket  ogifta             20 män          62487  1968  62487
12 Riket  ogifta             20 kvinnor      50089  1968 -50089
13 Riket  ogifta             21 män          60714  1968  60714
14 Riket  ogifta             21 kvinnor      43413  1968 -43413
15 Riket  ogifta             22 män          56801  1968  56801
16 Riket  ogifta             22 kvinnor      36301  1968 -36301
17 Riket  ogifta             23 män          49862  1968  49862
18 Riket  ogifta             23 kvinnor      29227  1968 -29227
19 Riket  ogifta             24 män          42143  1968  42143
20 Riket  ogifta             24 kvinnor      23155  1968 -23155

CodePudding user response:

In base R, we can do

df$neg_kv <-  c(1, -1)[(df$gender == "kvinnor")   1] * df$population

CodePudding user response:

Just for fun here are 2 more alternative ways:

  1. dplyr purrr:
library(dplyr)
library(purrr)
df %>%
  mutate(id = row_number()) %>% 
  mutate(neg_kv = population) %>% 
  group_split(gender == "kvinnor", .keep=FALSE) %>% 
  modify_at(2, ~ mutate(., neg_kv = population * -1)) %>% 
  bind_rows() %>% 
  arrange(id) %>% 
  select(-id)
  1. base R: Using indexing:
index <- df$gender == "kvinnor"
df$neg_kv <- df$population
df$neg_kv[index] <- df$population[index] *-1
df

Output:

   region marriage_status   age gender  population  year neg_kv
   <chr>  <chr>           <dbl> <chr>        <dbl> <dbl>  <dbl>
 1 Riket  ogifta             15 män          56031  1968  56031
 2 Riket  ogifta             15 kvinnor      52959  1968 -52959
 3 Riket  ogifta             16 män          55917  1968  55917
 4 Riket  ogifta             16 kvinnor      52979  1968 -52979
 5 Riket  ogifta             17 män          55922  1968  55922
 6 Riket  ogifta             17 kvinnor      52050  1968 -52050
 7 Riket  ogifta             18 män          58681  1968  58681
 8 Riket  ogifta             18 kvinnor      51862  1968 -51862
 9 Riket  ogifta             19 män          60387  1968  60387
10 Riket  ogifta             19 kvinnor      49750  1968 -49750
11 Riket  ogifta             20 män          62487  1968  62487
12 Riket  ogifta             20 kvinnor      50089  1968 -50089
13 Riket  ogifta             21 män          60714  1968  60714
14 Riket  ogifta             21 kvinnor      43413  1968 -43413
15 Riket  ogifta             22 män          56801  1968  56801
16 Riket  ogifta             22 kvinnor      36301  1968 -36301
17 Riket  ogifta             23 män          49862  1968  49862
18 Riket  ogifta             23 kvinnor      29227  1968 -29227
19 Riket  ogifta             24 män          42143  1968  42143
20 Riket  ogifta             24 kvinnor      23155  1968 -23155
  • Related