Представьте набор данных:
df1 <- tibble::tribble(~City, ~Year, ~Coffee, ~Tea, ~Year, ~Sugar, ~At, ~Empty,
"NY", "2020", "", "", "2020", "2", "", "",
"NY", "2019", "5", "3", "2019", "5", "", "",
"City", "Year", "Coffee", "Tea", "Year", "Sugar", "", "",
"ATL", "2020", "", "", "2020", "2", "", "",
"ATL", "2019", "5", "3", "2019", "5", "", "",
"Data input by: Alex", "", "", "", "", "", "", "",
"BOS", "Year", "", "Coffee", "", "Tea", "Sugar", "",
"BOS", "2020", "", "7", "2020", "8", "3", "",
"BOS", "2019", "", "7", "2019", "7", "2", "",
"MS", "Year", "Frappacino", "Green Tea", "", "Coffee", "Sugar", "",
"MS", "2020", "5", "6", "2019", "8", "3", "",
"MS", "2019", "5", "5", "2020", "8", "3", "",
"City", "Year", "Coffee", "Tea", "Year", "Sugar", "At", "",
"HW", "2020", "500", "300", "2020", "200", "", "",
"HW", "2019", "450", "320", "2019", "180", "", "",
"Data input by: Aleksanteri", "", "", "", "", "", "", "",
"Kaupunki", "Vuosi", "Kahvi", "Tee", "Vuosi", "At", "Sokeri", "",
"HEL", "2020", "7", "4", "2018", "", "4", "",
"HEL", "2019", "7", "4", "2019", "", "4", "",
"HEL", "2018", "6", "3", "2020", "", "5", "")
Тот же набор данных (для визуального представления):
Проблемы:
Есть ли простой способ справиться с такими проблемами с данными?
Я только что столкнулся с этой проблемой. Я решал ее одну за другой, а затем остановился на идее, что должен быть простой метод для всего.
Спасибо, Роман. Это может быть хорошо именно для этого набора данных. Но если у вас огромный набор данных, это усложняет использование Excel. Буду благодарен даже за самое простое среди сложных решений :)
Единственный успех, который у меня был с подобными наборами данных, — это чтение их по строкам и обдумывание «откуда мне знать, что делать с каждой строкой» и, таким образом, сборка ряда правил. Это медленная и раздражающая работа по его настройке.
Спасибо, Пол! Я сделал алгоритм, который уменьшает количество ячеек, которые нужно искать (что помогает). Но я уверен, что должно быть какое-то более простое решение. Пожалуйста, не стесняйтесь выражать любые идеи или коды :)
Проблемы с фактическим набором данных все те же :) Итак, я попытался воспроизвести проблемы на примере небольшого набора данных :)
Предполагая, что годы не перекошены по горизонтали, и в вашем выводе вы можете сократить столбец до одного года, вы можете расплавить свою таблицу на c("City", "Year")
. Затем интерпретируйте столбец значений для тех, которые представляют собой строку букв, сравните их с переменной и исправьте столбец переменной, где это необходимо.
OpenRefine можно использовать для исследовательского анализа и обработки данных, но это все равно будет процесс, в значительной степени управляемый человеком.
Немного быстро и грязно, и вам может понадобиться некоторая тонкая настройка, если ваши данные еще более изменчивы, чем я предполагал.
Ключевым требованием в моем подходе является то, что ваша первая строка, по крайней мере, город, имеет правильное имя и что год правильно назван в первой строке и в известной позиции (вы можете найти его по именам вашей таблицы. Но годы не могут быть перекошены по столбцам.
Я использую data.table
здесь
library(data.table)
setDT(df1)
# find the year columns
cols <- names(df1)
ypos <- last(which(cols %in% "Year"))
# split your data to deal with differences in years per row (for HEL)
dt <- rbindlist(list(df1[, 1L:(ypos-1L), with = F], df1[, c(1L, ypos:length(cols)), with = F]), fill = T)
# melt data and take the first row as headers we will fix later on
# this only works though when you know the Year column is never shifted to another column
dt <- melt.data.table(dt, id.vars = c("City", "Year"), variable.factor = F)
dt <- dt[!(Year == "" & value == ""),]
dt <- dt[, City := fifelse(City %in% c("City", "Kaupunki"), shift(City, type = "lead"), City)]
dt <- dt[!(value == "" | value == "At")]
v_f <- c("Kahvi", "Tee", "Sokeri")
v_t <- c("Coffee", "Tea", "Sugar")
dt[, value := str_replace_all(value,setNames(v_t, v_f))]
dt[, new_variable := first(value), rleid(City)]
dt[is.na(as.numeric(new_variable)), variable := new_variable][, new_variable := NULL]
dt[, value := as.numeric(value)]
dt <- dt[!is.na(value)]
dt[, value := fifelse(value > 100, value / 100, value)]
dcast(dt, City + Year ~ variable, value.var = "value")
Полученные результаты
City Year Coffee Frappacino Green Tea Sugar Tea
1: ATL 2019 5.0 NA NA 5.0 3.0
2: ATL 2020 NA NA NA 2.0 NA
3: BOS 2019 7.0 NA NA 2.0 7.0
4: BOS 2020 7.0 NA NA 3.0 8.0
5: HEL 2018 6.0 NA NA 4.0 3.0
6: HEL 2019 7.0 NA NA 4.0 4.0
7: HEL 2020 7.0 NA NA 5.0 4.0
8: HW 2019 4.5 NA NA 1.8 3.2
9: HW 2020 5.0 NA NA 2.0 3.0
10: MS 2019 8.0 5 5 3.0 NA
11: MS 2020 8.0 5 6 3.0 NA
12: NY 2019 5.0 NA NA 5.0 3.0
13: NY 2020 NA NA NA 2.0 NA
слишком много вопросов, чтобы найти простые условия. Я бы порекомендовал преобразовать его в Excel.