Есть ли функция R для очистки грязных зарплат в символьном формате?

#r #tidyverse #data-cleaning

#r #tidyverse #очистка данных

Вопрос:

У меня есть столбец с грязными данными о зарплате. Мне интересно, есть ли пакет, в котором есть функция, созданная специально для очистки такого типа грязных данных. Мои данные выглядят так:

 data.frame(salary = c("40,000-60,000", "40-80K", "$100,000", 
                  "$70/hr", "Between $65-80/hour", "$100k",
                  "50-60,000 a year", "90"))
#>                salary
#> 1       40,000-60,000
#> 2              40-80K
#> 3            $100,000
#> 4              $70/hr
#> 5 Between $65-80/hour
#> 6               $100k
#> 7    50-60,000 a year
#> 8                  90
 

Создано 2020-12-16 пакетом reprex (версия 0.3.0)

и я бы хотел, чтобы чистый столбец был числовым на годовом уровне. Я знаю, как очистить этот столбец вручную, мне просто интересно, есть ли какие-либо другие пакеты, которые могут помочь (кроме readr::parse_number() )

Ожидаемый результат будет выглядеть так:

 #>   output
#> 1  50000
#> 2  60000
#> 3 100000
#> 4 145600
#> 5 150800
#> 6 100000
#> 7  55000
#> 8  90000
 

Комментарии:

1. Можете ли вы показать ожидаемый формат вывода

2. да, один момент

3. Если посмотреть на данные, это больше похоже на пользовательский случай

4. особенно 70 / час, требуется рабочий час / год

5. В почасовом множителе я не уверен. Кроме этого, вы можете проверить решение ниже

Ответ №1:

Вот несколько первых шагов, которые вы можете попробовать. Я определяю две функции: одна заменяет k или K тремя нулями. Другой добавляет начальные нули, если одно число обозначается в тысячах, а другое — нет.

 rem_k <- function(x) {
  sub("(\d)[kK]", "\1,000", x)
}

add_zero <- function(x) {
  ifelse(grepl("[1-9]0\-\d[0,]{2,}", x), sub("([1-9]0)(\-\d[0,]{2,})", "\1,000\2", x), x)
}
 

Наконец, я удаляю все несущественные символы:

 df %>% 
  mutate(salary2 = gsub("[^0-9,\-]", "", add_zero(rem_k(salary))))

               salary       salary2
1       40,000-60,000 40,000-60,000
2              40-80K 40,000-80,000
3            $100,000       100,000
4              $70/hr            70
5 Between $65-80/hour         65-80
6               $100k       100,000
7    50-60,000 a year 50,000-60,000
8                  90            90
 

Ответ №2:

Один из вариантов — создать столбец ‘salary1’, содержащий только цифры, а - затем разделить separate его на два столбца по - mutate значениям этих столбцов на основе совпадений подстрок в исходном столбце, т.е. K|k или hr|hour , т.е. умножить их на 1000 ( K|k ) или на почасовую, в зависимости от количества часов длягод, с case_when и получить rowMeans из этих столбцов

 library(dplyr)
library(stringr)
library(tidyr)
df1 %>% 
   mutate(salary1 = str_remove_all(salary, '[^0-9-] ')) %>% 
   separate(salary1, into = c('salary1', 'salary2'), 
           convert = TRUE, extra = 'drop') %>%
   mutate(across(c(salary1, salary2),
    ~ case_when(str_detect(salary, "[Kk]") ~ . * 1000, 
               str_detect(salary, 'hr|hour') ~ . * 40 * 4 * 12, 
               nchar(.) < 5 ~ as.numeric(str_pad(., pad = '0', 
                   side = 'right', width = 5)),
             TRUE ~ as.numeric(.)))) %>% 
    transmute(output = rowMeans(select(., salary1, salary2), na.rm = TRUE))
 

-вывод

 #  output
#1  50000
#2  60000
#3 100000
#4 134400
#5 139200
#6 100000
#7  55000
#8  90000