#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