ITPub博客

首页 > > > 【R语言】tidyverse之六:修改列

【R语言】tidyverse之六:修改列

作者:浪花小雨滴 时间:2020-06-17 10:47:12 0 删除 编辑

修改数据框的列,计算新列。

一. 创建新列

用 dplyr 包中的 mutate() 创建或修改列:

iris %>%
  as_tibble(iris) %>%
  mutate(new_column = "recycle_me")

若只给新列提供长度为 1 的向量,则循环使用得到值相同的一列;正常是以长度等于行数的向量赋值:

iris %>%
  as_tibble(iris) %>%  
  mutate(new_column = rep_len(month.name, length.out=n()))

注: n() 返回group size, 未分组则为总行数。

二. 计算新列

用数据框的列计算新列,若修改当前列,只需要赋值给原列名。

iris %>%
  as_tibble(iris) %>%
  mutate(add_all = Sepal.Length + Sepal.Width + Petal.Length + Petal.Width)

注意,不能用sum(), 它会将整个列的内容都加起来,类似的还有 mean().

在同一个 mutate() 中可以同时创建或计算多个列,它们是从前往后依次计算,所以可以使用前面新创建的列。例如,

  • 计算 iris 中所有 Petal.Length 的中位数;
  • 创建标记列,若 Petal.Length 大于中位数则为 TRUE,否则为 FALSE;
  • 用 as.numeric() 将 TRUE/FALSE 转化为 1/0
iris %>%
  as_tibble() %>%
  mutate(median_petal_length = median(Petal.Length),
         has_long_petals = Petal.Length > median_petal_length,
         has_long_petals = as.numeric(has_long_petals)) %>%  
  select(Petal.Length, median_petal_length, has_long_petals) 

三. 修改多列

实现应用函数到数据框的多列。

  1. mutate_all()——应用函数到所有列

将所有列转化为小写:

msleep %>%
  mutate_all(tolower)

2. mutate_if()——应用函数到满足条件的列

将所有 Double 型的列,转化为 Integer:

iris %>%
  mutate_if(is.double, as.integer)

也可以对满足条件的列应用自定义函数,用更简洁的匿名函数写法,还可以使用管道操作。例如,将所有因子列,转化为 Character 型,再变成大写:

iris %>%
  as_tibble() %>%
  mutate_if(is.factor,
            ~ as.character(.) %>% 
              str_to_upper()
  )

3. mutate_at()——应用函数到指定的列

通常借助辅助选择函数 contains() 和 matches(),再套了一个 vars() 来选择列。常用来对某些测量列作单位转换。

例如,在不影响其它数值列的情况下,将 iris 中的 length 和 width 测量单位从厘米变成毫米:

iris %>%
  as_tibble() %>%
  mutate_at(vars(contains("Length"), contains("Width")), ~ .*10) %>%
  rename_at(vars(matches("Length|Width")), ~ paste0(., "_mm"))

四. 替换 NA

  1. replace_na()

实现用同一个值替换一列中的所有 NA 值,该函数接受一个命名列表,其成分为“列名=替换值”:

starwars %>%
  replace_na(list(hair_color = "UNKNOWN",
                  birth_year = 99999))

2. fill()

用前一个(或后一个)非缺失值填充 NA。有些表在记录时,会省略与上一条记录相同的内容,如下表:

gap_data <- tribble(
  ~site,  ~species,  ~sample_num, ~bees_present,
  "Bilpin", "A. longiforlia", 1, TRUE,
   NA,       NA,              2, TRUE,
   NA,       NA,              3, TRUE,
   NA,       "A. elongata",   1, TRUE,
   NA,        NA,             2, FALSE,
   NA,        NA,             3, TRUE,
  "Grose Vale",  "A. terminalis", 1, FALSE,
   NA,        NA,                 2, FALSE,
   NA,        NA,                 2, TRUE
)
gap_data

Tidyr 包中的 fill() 适合处理这种结构的 NAs, 默认是向下填充,用上一个非缺失值填充这些 NAs:

gap_data %>% 
  fill(site, species)

五. 重新编码

经常需要对列中的值进行重新编码。

  1. 两类别情形:if_else()

用 if_else() 作 yes / no 决策以确定用哪个值做替换:

warpbreaks %>%
  mutate(breed = if_else(wool == "A",
                         true = "Merino",
                         false = "Corriedale")) %>%
  sample_frac(size = 0.15)

2. 多类别情形:case_when()

用 case_when() 做更多条件下的替换,避免使用很多 if_else() 嵌套。

warpbreaks %>%
  mutate(tension=case_when(tension == "H" ~ "High",
                           tension == "M" ~ "Medium",
                           tension == "L" ~ "Low",
                           TRUE ~ NA_character_)) %>%
  sample_frac(size = 0.15)

使用 case_when() 时,需要注意:

  • 本例是提供两边公式:

- 左边是返回TRUE或FALSE的表达式或函数

- 中间是 ~

- 右边是若左边表达式为 TRUE,则重新编码的值,也可以是表达式或函数

  • 每个分支条件将从上到下的计算,并接受第一个 TURE 条件;
  • 一个好的策略是,用最后一个分支决定若其它条件都不为 TRUE 时该怎么做。为此,本例最后一个分支直接用 TRUE 作为公式左边,若某行的 tension 值不是 H/M/L,将被重新编码为 NA_character_


参考文献:

  1. Desi Quintans, Jeff Powell. Working in the Tidyverse. hiercourse.com/
  2. SuZan. Data Wrangling Part 2: Transforming your columns into the right shape. suzan.rbind.io/2018/02/
  3. Garrett Grolemund, Hadley Wickham. R for Data Science. r4ds.had.co.nz/


____________________________________

转载请注明,禁止用于出版。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3127025/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-05-16

  • 博文量
    4259
  • 访问量
    40075