Я пытаюсь осмыслить замыкания, и я думаю Я нашел случай где они могут быть полезны.
Мне нужно поработать со следующими частями:
Идея состоит в том, что при наличии некоторого data.frame с неаккуратными названиями штатов (заглавная буква указана как «Вашингтон, округ Колумбия», «Вашингтон, округ Колумбия», «Округ Колумбия» и т. Д.?), Чтобы одна функция возвращала тот же data.frame с удаленным столбцом имени штата и оставшимися только кодами идентификатора штата. Тогда последующие слияния могут происходить последовательно.
Я могу сделать это любым количеством способов, но один из способов, который кажется особенно элегантным, - это разместить карту слияния и регулярное выражение, а код обрабатывает все внутри замыкания (следуя идее, что замыкание - это функция с данными).
Вопрос 1: Разумная ли это идея?
Вопрос 2: Если да, как мне это сделать в R?
Вот дурацкая простая функция очистки имен состояний, которая работает с данными примера:
cleanStateNames <- function(x) {
x <- tolower(x)
x[grepl("columbia",x)] <- "DC"
x
}
Вот несколько примеров данных, на которых в конечном итоге будет запущена функция:
dat <- structure(list(state = c("Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "District of Columbia",
"Florida"), pop08 = structure(c(29L, 44L, 40L, 18L, 25L, 30L,
22L, 48L, 36L, 13L), .Label = c("1,050,788", "1,288,198", "1,315,809",
"1,316,456", "1,523,816", "1,783,432", "1,814,468", "1,984,356",
"10,003,422", "11,485,910", "12,448,279", "12,901,563", "18,328,340",
"19,490,297", "2,600,167", "2,736,424", "2,802,134", "2,855,390",
"2,938,618", "24,326,974", "3,002,555", "3,501,252", "3,642,361",
"3,790,060", "36,756,666", "4,269,245", "4,410,796", "4,479,800",
"4,661,900", "4,939,456", "5,220,393", "5,627,967", "5,633,597",
"5,911,605", "532,668", "591,833", "6,214,888", "6,376,792",
"6,497,967", "6,500,180", "6,549,224", "621,270", "641,481",
"686,293", "7,769,089", "8,682,661", "804,194", "873,092", "9,222,414",
"9,685,744", "967,440"), class = "factor")), .Names = c("state",
"pop08"), row.names = c(NA, 10L), class = "data.frame")
И образец карты слияния (фактическая связывает коды FIPS с состояниями, поэтому ее нельзя тривиально сгенерировать):
merge_map <- data.frame(state=dat$state, id=seq(10) )
РЕДАКТИРОВАТЬ Создание Ниже приведен ответ с нарушением лямбды, вот попытка использования функции:
prepForMerge <- local({
merge_map <- structure(list(state = c("alabama", "alaska", "arizona", "arkansas", "california", "colorado", "connecticut", "delaware", "DC", "florida" ), id = 1:10), .Names = c("state", "id"), row.names = c(NA, -10L ), class = "data.frame")
list(
replace_merge_map=function(new_merge_map) {
merge_map <<- new_merge_map
},
show_merge_map=function() {
merge_map
},
return_prepped_data.frame=function(dat) {
dat$state <- cleanStateNames(dat$state)
dat <- merge(dat,merge_map)
dat <- subset(dat,select=c(-state))
dat
}
)
})
> prepForMerge$return_prepped_data.frame(dat)
pop08 id
1 4,661,900 1
2 686,293 2
3 6,500,180 3
4 2,855,390 4
5 36,756,666 5
6 4,939,456 6
7 3,501,252 7
8 591,833 9
9 873,092 8
10 18,328,340 10
Прежде чем я буду считать этот вопрос решенным, остаются две проблемы:
Вызов prepareForMerge $ return_prepped_data.frame (dat)
каждый раз болезненно. Есть ли способ иметь функцию по умолчанию, чтобы я мог просто вызвать препФорМерже (дат)? Я предполагаю, что не знаю, как это реализовано, но, возможно, есть по крайней мере соглашение для fxn по умолчанию ....
Как мне избежать смешивания данных и кода в определении merge_map? В идеале я бы очистил merge_map в другом месте, а затем просто взял бы его внутри закрытия и сохранил.