Ho una funzione che funziona, per un data.table (data.frame) di 1 riga, ma non lavoro per l'intero data.table. Vorrei estendere la funzione per prendere in considerazione tutte le righe dei dati di input.table.estensione di una funzione che accetta un data.table come argomento per utilizzare la tabella completa (invece di un sottoinsieme)
Il nocciolo dell'argomento è il seguente:
A data.table (tryshort3
) se un campo è una stringa, deve essere sostituita con un'altra stringa da un'altra data.table (mapping
), MRE come segue :
#this is the original data.table
tryshort3 <- structure(list(country = c("AT", "AT", "MT", "DE", "CH", "XK"
), name = c("ASDF AG", "ASDF GMBH", "ASDF DF", "ASDF KG", "ASDF SA",
"ASDF DAF"), address = c("ACDSTR. 3", "ACDSTR. 4", "ACDSTR. 5",
"ACDSTR. 6", "ACDSTR. 7", "ACDSTR. 8")), .Names = c("country",
"name", "address"), row.names = c(NA, -6L), class = c("data.table",
"data.frame"))
#this is the "mapping
mapping <- structure(list(country = c("AT", "AT", "DE", "DE", "HU"), short.form = c("AG",
"GMBH", "GMBH", "EV", "EV"), long.form = c("AKTIENGESELLSCHAFT",
"GESELLSCHAFT MIT BESCHRANKTER HAFTUNG", "GESELLSCHAFT MIT BESCHRANKTER HAFTUNG",
"EINGETRAGENE VEREIN", "EGYENI VALLALKOZO")), .Names = c("country",
"short.form", "long.form"), row.names = c(NA, -5L), class = c("data.table",
"data.frame"), sorted = "country")
#this is the function that I am using (please not that both data.tables are keyed, but that has currently no say in the output (just avoids throwing an error):
substituting_short_form <- function(input) {
#supply one data.frame of 1 row, the other data.frame is external to the function
#get country from input
setkey(input,country)
setkey(mapping,country)
matched_country <- input$country
#subset of mapping to only the country from the input
matched_map <- mapping[country == matched_country]
#get list of short.forms from matched
list_of_relevant_short_forms <- matched_map[,short.form]
#which one matches will return true if there is any match, THIS IS A NUMBER THAT WILL HAVE TO BE MATCHED TO mapping again to retrieve the correct form
#error catching for when there is no short form found, or no country found if there is no long form it does not matter!
indextrue <- tryCatch(which(unlist(lapply(list_of_relevant_short_forms, function(y) grepl(y, input$name)))), error = function(e) return(input))
#substitute
pattern_to_substitute <- paste0("(\\s|^)", matched_map[indextrue,short.form], "(\\s|$)")
pattern_to_replace <- paste0("\\1", matched_map[indextrue,long.form], "\\2")
input$name[1] <- gsub(pattern = pattern_to_substitute, replacement = pattern_to_replace,input$name , perl = TRUE)
return(input)
}
in breve, cosa questa funzione sta facendo, sta prendendo tryshort3
asn un ingresso (attualmente solo lavorando con tryshort3[1,]
) e sostituisce nel campo "nome" il valore trovato nella tabella mapping
, in questo modo:
> tryshort3[1,]
country name address
1: AT ASDF AG ACDSTR. 3
> substituting_short_form(tryshort3[1,])
country name address
1: AT ASDF AKTIENGESELLSCHAFT ACDSTR. 3
Quello che vorrei, fornisco come input la piena data.table, e ottenere lo stesso risultato (un data.table di stessa lunghezza), ecco il mio risultato atteso:
country name address
1: AT ASDF AKTIENGESELLSCHAFT ACDSTR. 3
2: AT ASDF GESELLSCHAFT MIT BESCHRANKTER HAFTUNG ACDSTR. 4
3: CH ASDF SA ACDSTR. 7
4: DE ASDF KG ACDSTR. 6
5: MT ASDF DF ACDSTR. 5
6: XK ASDF DAF ACDSTR. 8
La soluzione che vorrei sarebbe qualcosa all'interno della funzione apply(tryshort3, 1, function(x) substituting_short_form(x))
, forse utilizzando le funzionalità di indicizzazione di entrambi i dati.tables, o forse usando gapply
da nlme
da dentro?
grazie a @David! :-) Ho sentito che c'era un modo per evitare il ifelse ;-) – Cath