Utilizzo di data.table
in R
, Sto tentando di eseguire un'operazione sul sottoinsieme escluso l'elemento selezionato. Sto usando l'operatore by
, ma non so se questo è l'approccio giusto.R: Data.table su sottoinsieme escluso valore
Ecco un esempio. Per esempio. il valore per Delta
in IAH:SNA
è (3 + 3)/2 che è la media di Stops
in IAH:SNA
una volta che Delta
è stato escluso.
library(data.table)
s1 <- "Market Carrier Stops
IAH:SNA Delta 1
IAH:SNA Delta 1
IAH:SNA Southwest 3
IAH:SNA Southwest 3
MSP:CLE Southwest 2
MSP:CLE Southwest 2
MSP:CLE American 2
MSP:CLE JetBlue 1"
d <- data.table(read.table(textConnection(s1), header=TRUE))
setkey(d, Carrier, Market)
f <- function(x, y){
subset(d, !(Carrier %in% x) & Market == y, Stops)[, mean(Stops)]}
d[, s := f(.BY[[1]], .BY[[2]]), by=list(Carrier, Market)]
## Market Carrier Stops s
## 1: MSP:CLE American 2 1.666667
## 2: IAH:SNA Delta 1 3.000000
## 3: IAH:SNA Delta 1 3.000000
## 5: IAH:SNA Southwest 3 1.000000
## 6: IAH:SNA Southwest 3 1.000000
## 7: MSP:CLE Southwest 2 1.500000
## 8: MSP:CLE Southwest 2 1.500000
La soluzione di cui sopra esegue molto male su grandi insiemi di dati (è essenzialmente un mapply
), ma non sono sicuro come farlo in modo veloce data.table
-come modo.
Forse si potrebbe (in modo dinamico) generare un fattore che lo fa? Non sono sicuro di come. . .
C'è un modo per migliorarlo?
Edit: Solo per il gusto di farlo, ecco un modo per ottenere una versione più grande di quanto sopra
library(data.table)
dl.dta <- function(...){
## input years ..
years <- gsub("\\.", "_", c(...))
baseurl <- "http://www.transtats.bts.gov/Download/"
names <- paste("Origin_and_Destination_Survey_DB1BMarket", years, sep="_")
info <- t(sapply(names, function(x) file.exists(paste(x, c("zip", "csv"), sep="."))))
to.download <- paste(baseurl, names, ".zip", sep="")[!apply(info, 1, any)]
if (length(to.download) > 0){
message("starting download...")
sapply(to.download,
function(x) download.file(x, rev(strsplit(x, "/")[[1]])[1]))}
to.unzip <- paste(names, "zip", sep=".")[!info[, 2]]
if (length(to.unzip > 0)){
message("starting to unzip...")
sapply(to.unzip, unzip)}
paste(names, "csv", sep=".")}
countWords.split <- function(x, s=":"){
## Faster on my machine than grep for some reanon
sapply(strsplit(as.character(x), s), length)}
countWords.grep <- function(x){
sapply(gregexpr("\\W+", x), length)+1}
fname <- dl.dta(2013.1)
cols <- rep("NULL", 41)
## Columns to keep: 9 is Origin, 18 is Dest, 24 is groups of airports in travel
## 30 is RPcarrier (reporting carrier).
## For more columns: 35 is market fare and 36 is distance.
cols[9] <- cols[18] <- cols[24] <- cols[30] <- NA
d <- data.table(read.csv(file=fname, colClasses=cols))
d[, Market := paste(Origin, Dest, sep=":")]
## should probably
d[, Stops := -2 + countWords.split(AirportGroup)]
d[, Carrier := RPCarrier]
d[, c("RPCarrier", "Origin", "Dest", "AirportGroup") := NULL]
Grazie, che lavora per la media. Ma forse 'f' è più complicato del' mean' e non presenta una soluzione in forma chiusa. – Rasmus
Bene, mostra un esempio di 'f'. – Roland
'f' potrebbe essere la norma della sottomatrice sul mercato' m' escluso il vettore 'c'. Sarebbe almeno più intuitivo operare un sottoinsieme. (La soluzione che fornisci è molto veloce btw!) – Rasmus