2013-09-05 6 views
16

Temo fortemente che questo sia stato chiesto e sarà downvoted, ma non ho trovato la risposta nei documenti (? "["), E ho scoperto che è difficile da cercare.Perché [- l'inserimento (ovvero la cancellazione) di colonne non è possibile con i nomi?

data(wines) 
# This is allowed: 
alcoholic <- wines[, 1] 
alcoholic <- wines[, "alcohol"] 
nonalcoholic <- wines[, -1] 
# But this is not: 
fail <- wines[, -"alcohol"] 

Conosco due soluzioni, ma sono frustrato per averne bisogno.

win <- wines[, !colnames(wines) %in% "alcohol"] # snappy 
win <- wines[, -which(colnames(wines) %in% "alcohol")] # snappier! 
+2

Le misure positive o negative di 'snappy' e' snappier'? Preferisco 'setdiff' in questi casi. Cosa ti aspetti che restituisca "-" alcool "? Non funziona da solo come comando, quindi perché dovrebbe funzionare quando si cerca di creare sottoinsiemi? – A5C1D2H2I1M1N2O1R2T1

+1

Forse non è una risposta al tuo "Perché" in termini su "perché qualcuno ha scelto di implementarlo in questo modo", ma comunque: da '? [': "Per' ['-indexing only: i, j, ... possono essere vettori logici (la tua alternativa '!') [...] possono anche essere numeri interi negativi (la tua alternativa 'quale'). – Henrik

+0

@AnandaMahto I era sarcastico, connotazioni così negative Aspettative di qualsiasi cosa in R? poche aspettative dopo la mia piccola esperienza con esso :) (Era umoristico). Puoi dare un esempio di come "setdiff" gestirà questo caso? –

risposta

17

Quando si esegue

wines[, -1] 

-1 viene valutata prima di essere utilizzato da [. Come sapete, l'operatore unario - non funzionerà con oggetto della classe character, così facendo lo stesso con "alcol" vi porterà a:

Error in -"alcohol" : invalid argument to unary operator 

è possibile aggiungere il seguente per le alternative:

wines[, -match("alcohol", colnames(wines))] 
wines[, setdiff(colnames(wines), "alcohol")] 

ma dovresti conoscere i rischi di indicizzazione negativa, ad esempio, vedere cosa succede se si digita "alcool" (sic.) Quindi il tuo primo suggerimento e l'ultimo qui (@ Ananda) dovrebbero essere preferiti. Potresti anche voler scrivere una funzione che genera un errore se fornisci un nome che non fa parte dei tuoi dati.

+0

'R> - 1' dà '[1] -1', quindi come funziona? Non sono così familiare con il modo in cui R funziona. È questo che vuoi dire? –

+0

Dovrò scrivere un compendio di idiomi per cancellare una colonna, grazie per le aggiunte :) –

+0

Sì, '-1' è qualcosa che valuta bene, quindi puoi passarlo come argomento alla funzione' [' saprà cosa farne. Dall'altro lato, '-" alcool "' no. Ha meno a che vedere con '[' è implementato, più con il fatto che non è possibile calcolare '-" alcohol "', quindi passarlo a '[' oa qualsiasi funzione. – flodel

0

è possibile ottenere il comportamento desiderato come segue:

data(iris) 
str(iris) 
delete <- which(colnames(iris) == "Species") 
iris2 <- iris[, -delete] 
str(iris2) 
+0

Ciò equivale a far corrispondere una singola stringa, invece di usare '% in%' per abbinare una lista di stringhe. –

+0

Questo potrebbe essere semplificato in 'deleted <- colnames (iris) ==" Species "; iris [! soppresso] '. Non hai bisogno di indicizzazione negativa quando hai il vettore logico. – Marek

3

ne dite di scrivere un po 'di semplice funzione e bastone nel vostro .Rprofile. Qualcosa di simile ...

dropcols <- function(df , cols){ 
    out <- df[ , !names(df) %in% cols] 
    return(out) 
} 

# To use it.... 
data(mtcars) 
head(dropcols(mtcars , "mpg")) 
#     cyl disp hp drat wt qsec vs am gear carb 
#Mazda RX4   6 160 110 3.90 2.620 16.46 0 1 4 4 
#Mazda RX4 Wag  6 160 110 3.90 2.875 17.02 0 1 4 4 
#Datsun 710   4 108 93 3.85 2.320 18.61 1 1 4 1 
#Hornet 4 Drive  6 258 110 3.08 3.215 19.44 1 0 3 1 
#Hornet Sportabout 8 360 175 3.15 3.440 17.02 0 0 3 2 
#Valiant    6 225 105 2.76 3.460 20.22 1 0 3 1 
+0

Sì, è un modo utile per risolverlo. Non molto portatile comunque per gli altri quindi sono un po 'poco incline a farlo. Ho evitato questo genere di cose in generale, anche per questo motivo, ma dimentico sempre di sincronizzare il mio lavoro con la macchina da casa con il portatile, ecc. E di dimenticare cosa c'è nel mio profilo .Rprile comunque! –

6

Un altro metodo che utilizza l'indicizzazione numerica e generalizza a situazioni in cui si wnat per rimuovere un gruppo di colonne con nomi simili:

dfrm[ , -grep("^val", names(dfrm))] #remove columns starting with "val" 

(ho dato il mio voto a flodel, dal momento che la sua risposta descriveva "perché" un "segno meno" non funzionava, essenzialmente perché gli autori R non sovraccaricarono l'operatore "-" per quello scopo, non sovraccaricarono "+" per fare concatenazione nel modo in cui alcune lingue lo hanno fatto.

+0

Quindi * potrebbero * essere sovraccaricati se gli sviluppatori lo hanno scelto? –

+0

@adifferentben Oppure potresti sovraccaricare l'op da te se ne hai il coraggio :-). –

+0

Gli autori dei sistemi di plotaggio e ggplot2 hanno sovraccaricato l'operatore "+", quindi non ci sono barriere fondamentali al sovraccarico "-". –

7

Un'altra possibilità:

subset(wines,select=-alcohol) 

Si può anche fare

subset(wines,select=-c(alcohol,other_drop)) 

In realtà, se si dispone di un insieme contiguo di colonne da eliminare, si può anche

subset(wines,select=-(first_drop:last_drop)) 

che può essere utile (anche se IMO dipende pericolosamente dall'ordine delle colonne, cosa che potrebbe essere fragile: potrei preferire una soluzione basata su grep se ci fosse un modo per identificare le colonne, o una definizione separata più esplicita dei gruppi di colonne).

In questo caso, subset utilizza una valutazione non standard, che come è stato discusso altrove può essere pericolosa in alcuni contesti. Ma mi piace ancora per la semplice manipolazione dei dati di primo livello grazie alla sua leggibilità.

+1

La funzione sottoinsieme converte l'espressione di selezione in numeri tramite un vettore di numeri denominato, motivo per cui il metodo ":" funziona. –

+0

sì ........... –

+1

@DWin, '? Subset' dice' Questa è una funzione di convenienza destinata all'uso interattivo. Per la programmazione è meglio usare le funzioni di subsetting standard come [, e in particolare la valutazione non standard del sottoinsieme di argomenti può avere conseguenze impreviste. Perché? Quali sono le valutazioni non standard a cui si riferisce. Quelli che Ben Bolker ha elencato? –

3

non riesco a trovare questo nella documentazione, ma la seguente sintassi funziona con data.table:

dt = data.table(wines) 

dt[, !"alcohol", with = F] 

e si può anche avere una lista di colonne, se ti piace:

dt[, !c("Country", "alcohol"), with = F] 

E 'stato appena documentato in NEWS per la versione 1.8.4 sembra:

Quando con = FALSE, "!" potrebbe anche essere un prefisso su j, # 1384ii. Questo seleziona tutte tranne le colonne con nome.

DF[,-match("somecol",names(DF))] 
# works when somecol exists. If not, NA causes an error. 

DF[,-match("somecol",names(DF),nomatch=0)] 
# works when somecol exists. Empty data.frame when it doesn't, silently. 

DT[,-match("somecol",names(DT)),with=FALSE] 
# same issues. 

DT[,setdiff(names(DT),"somecol"),with=FALSE] 
# works but you have to know order of arguments, and no warning if missing 

vs

DT[,!"somecol",with=FALSE] 
# works and easy to read. With (helpful) warning if somecol isn't there. 

Ma l'soprattutto copia ogni colonna diversa quello eliminato. Più di solito:

DT[,somecol:=NULL] 

per eliminare la colonna per nome per riferimento.

Problemi correlati