0
votes

Assuming the following dataset:

    df <- structure(list(id = 1:9, city = structure(c(1L, 7L, 2L, 6L, 4L, 
9L, 3L, 8L, 5L), .Label = c("bj", "gz", "lz", "nj", "sh", "sz", 
"tj", "wh", "xa"), class = "factor")), class = "data.frame", row.names = c(NA, 
-9L))

enter image description here

How could create a new column direction based on conditions:

if city is in list ['bj', 'tj'], then returns north for direction, if in ['sz', 'nj', 'sh'] returns east, if in ['xa', 'lz'] returns west, if in ['wh'] returns center, if in ['gz', 'sz'] returns south.

The expected result will like this:

enter image description here

My code:

df %>%
  filter(city %in% c('bj', 'tj')) %>%
  mutate(direction = 'north')

Out:

enter image description here

4

4 Answers

2
votes

Use case_when :

library(dplyr)

df %>%
  mutate(direction = case_when(city %in% c('bj', 'tj') ~ 'north', 
                               city %in% c('sz', 'nj', 'sh') ~ 'east', 
                               city %in% c('xa', 'lz') ~ 'west', 
                               city %in% c('wh') ~ 'center', 
                               city %in% c('gz', 'sz') ~ 'south', 
                               ))

#  id city direction
#1  1   bj     north
#2  2   tj     north
#3  3   gz     south
#4  4   sz      east
#5  5   nj      east
#6  6   xa      west
#7  7   lz      west
#8  8   wh    center
#9  9   sh      east
2
votes

You can do it in an easy way using basic R data.frame manipulation:

df$direction <- ""
df[df$city %in% c('bj', 'tj'), "direction"] <- "north"
df[df$city %in% c('sz', 'nj', 'sh'),"direction"] <- "east"
df[df$city %in% c('xa', 'lz'), "direction"] <- "west"
df[df$city %in% c('wh'), "direction"] <- "center"
df[df$city %in% c('gz', 'sz'), "direction"] <- "south"
 
df
  id city direction
1  1   bj     north
2  2   tj     north
3  3   gz     south
4  4   sz     south
5  5   nj      east
6  6   xa      west
7  7   lz      west
8  8   wh    center
9  9   sh      east
1
votes

Using nested ifelse statements can do the job as well.

df$direction=ifelse(df$city %in% c("bj","tj"), yes = "north",
          ifelse(df$city %in% c('sz', 'nj', 'sh'), yes = "east",
          ifelse(df$city %in% c("xa", "lz"), yes = "west",
          ifelse(df$city %in% c("gz", "sz"), yes = "south", no = "center"))))
1
votes

You can try stack to create a dictionary first and then match the cities, e.g.,

d <- stack(
  list(
    north = c("bj", "tj"),
    east = c("sz", "nj", "sh"),
    west = c("xa", "lz"),
    center = "wh",
    south = c("gz", "sz")
  )
)

df <- transform(
  df,
  direction = d$ind[match(city,d$values)]
)

which gives

  id city direction
1  1   bj     north
2  2   tj     north
3  3   gz     south
4  4   sz      east
5  5   nj      east
6  6   xa      west
7  7   lz      west
8  8   wh    center
9  9   sh      east