Leggi solo le colonne selezionate


134

Qualcuno può dirmi come leggere solo i primi 6 mesi (7 colonne) per ogni anno dei dati di seguito, ad esempio utilizzando read.table()?

Year   Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec   
2009   -41  -27  -25  -31  -31  -39  -25  -15  -30  -27  -21  -25
2010   -41  -27  -25  -31  -31  -39  -25  -15  -30  -27  -21  -25 
2011   -21  -27   -2   -6  -10  -32  -13  -12  -27  -30  -38  -29

5
È duplicato di Ways leggere solo le colonne selezionate da un file in R? , Dirk menziona NULLcome una colonna nella sua risposta .
Marek,


2
@CiroSantilli 法轮功 露 宪 六四 事件 法轮功 certo ma ... ho chiesto prima?
StarCub,

Non intendevo una relazione migliore / peggiore. Inoltre non ci sono duplicati su più siti, la rete di scambio di stack incoerente consente loro, a meno che non si attraversi un post :-)
Ciro Santilli 15 冠状 病 六四 事件 法轮功

Risposte:


157

Supponi che i dati siano in archivio data.txt, puoi usare l' colClassesargomento di read.table()per saltare le colonne. Qui i dati nelle prime 7 colonne sono "integer"e impostiamo le restanti 6 colonne per "NULL"indicare che dovrebbero essere saltate

> read.table("data.txt", colClasses = c(rep("integer", 7), rep("NULL", 6)), 
+            header = TRUE)
  Year Jan Feb Mar Apr May Jun
1 2009 -41 -27 -25 -31 -31 -39
2 2010 -41 -27 -25 -31 -31 -39
3 2011 -21 -27  -2  -6 -10 -32

Passare "integer"a uno dei tipi accettati come dettagliato in ?read.tablebase al tipo reale di dati.

data.txt Somiglia a questo:

$ cat data.txt 
"Year" "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
2009 -41 -27 -25 -31 -31 -39 -25 -15 -30 -27 -21 -25
2010 -41 -27 -25 -31 -31 -39 -25 -15 -30 -27 -21 -25
2011 -21 -27 -2 -6 -10 -32 -13 -12 -27 -30 -38 -29

ed è stato creato utilizzando

write.table(dat, file = "data.txt", row.names = FALSE)

dove datè

dat <- structure(list(Year = 2009:2011, Jan = c(-41L, -41L, -21L), Feb = c(-27L, 
-27L, -27L), Mar = c(-25L, -25L, -2L), Apr = c(-31L, -31L, -6L
), May = c(-31L, -31L, -10L), Jun = c(-39L, -39L, -32L), Jul = c(-25L, 
-25L, -13L), Aug = c(-15L, -15L, -12L), Sep = c(-30L, -30L, -27L
), Oct = c(-27L, -27L, -30L), Nov = c(-21L, -21L, -38L), Dec = c(-25L, 
-25L, -29L)), .Names = c("Year", "Jan", "Feb", "Mar", "Apr", 
"May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"), class = "data.frame",
row.names = c(NA, -3L))

Se il numero di colonne non è noto in anticipo, la funzione di utilità count.fieldsleggerà il file e conteggerà il numero di campi in ciascuna riga.

## returns a vector equal to the number of lines in the file
count.fields("data.txt", sep = "\t")
## returns the maximum to set colClasses
max(count.fields("data.txt", sep = "\t"))

1
@Benjamin Leggi le prime due righe del file usando l'argomento nrows. Quindi calcola quante colonne stai usando ncol()o comunque vuoi calcolare il numero di colonne da leggere / ignorare. Quindi leggi il file completo usando queste informazioni.
Gavin Simpson,

1
?? Se non conosci il numero di colonne, in quale altro modo lo determinerai senza leggerne un po 'per dedurne quante ce ne sono?
Gavin Simpson,

1
@BlueMagister Grazie per la modifica e la menzione di ciò count.fields()che automatizza il processo che ho suggerito nei commenti.
Gavin Simpson,

1
@ LéoLéopoldHertz 준영 No, e non sono sicuro di come una cosa funzionerebbe per le classi di riga come in un frame di dati, mentre ogni colonna può essere di tipo diverso, ogni riga è, per definizione e, di conseguenza, non vincolata. Sarà necessario filtrare le righe vuote ecc. Al momento dell'importazione.
Gavin Simpson,

1
@rmf è possibile passare count.fields()una connessione di testo, quindi leggere alcuni sottogruppi di righe usando txt <- readLines(....), quindi creare una connessione alle righe in lettura con <- textConnection(txt), quindi fare count.fields(txt). Assicurati di usare skipin count.fields()per saltare la riga di intestazione se ce n'è una; non puoi saltare le righe nel file usando readLines().
Gavin Simpson,

82

Per leggere un set specifico di colonne da un set di dati, esistono diverse altre opzioni:

1) Con freaddal data.tablepacchetto:

È possibile specificare le colonne desiderate con il selectparametro dal freaddal data.tablepacchetto. È possibile specificare le colonne con un vettore di nomi di colonna o numeri di colonna.

Per il set di dati di esempio:

library(data.table)
dat <- fread("data.txt", select = c("Year","Jan","Feb","Mar","Apr","May","Jun"))
dat <- fread("data.txt", select = c(1:7))

In alternativa, è possibile utilizzare il dropparametro per indicare quali colonne non devono essere lette:

dat <- fread("data.txt", drop = c("Jul","Aug","Sep","Oct","Nov","Dec"))
dat <- fread("data.txt", drop = c(8:13))

Tutto risulta in:

> data
  Year Jan Feb Mar Apr May Jun
1 2009 -41 -27 -25 -31 -31 -39
2 2010 -41 -27 -25 -31 -31 -39
3 2011 -21 -27  -2  -6 -10 -32

AGGIORNAMENTO: quando non si desidera freadrestituire un file data.table , utilizzare il data.table = FALSEparametro -par, ad esempio:fread("data.txt", select = c(1:7), data.table = FALSE)

2) Con read.csv.sqldal sqldfpacchetto:

Un'altra alternativa è la read.csv.sqlfunzione dal sqldfpacchetto:

library(sqldf)
dat <- read.csv.sql("data.txt",
                    sql = "select Year,Jan,Feb,Mar,Apr,May,Jun from file",
                    sep = "\t")

3) Con le read_*funzioni del readrpacchetto:

library(readr)
dat <- read_table("data.txt",
                  col_types = cols_only(Year = 'i', Jan = 'i', Feb = 'i', Mar = 'i',
                                        Apr = 'i', May = 'i', Jun = 'i'))
dat <- read_table("data.txt",
                  col_types = list(Jul = col_skip(), Aug = col_skip(), Sep = col_skip(),
                                   Oct = col_skip(), Nov = col_skip(), Dec = col_skip()))
dat <- read_table("data.txt", col_types = 'iiiiiii______')

Dalla documentazione una spiegazione per i caratteri usati con col_types:

ogni carattere rappresenta una colonna: c = carattere, i = numero intero, n = numero, d = doppio, l = logico, D = data, T = data ora, t = ora,? = indovina o _ / - per saltare la colonna


freadnon supporta i file compressi, tuttavia. I file di grandi dimensioni sono generalmente compressi.
CoderGuy123,

C'è una richiesta di funzionalità per abilitare questo in fread. Vale la pena notare che freadmolto probabilmente leggerà il file non compresso molto più velocemente di quanto read.tableleggerà il file compresso. Vedi qui per un esempio .
Jaap,

Alcuni file non compressi sono troppo grandi. Ad esempio, sto lavorando con 1000 file di genomi. Possono essere non compressi da 60 GB.
CoderGuy123,

1
Come probabilmente saprai, R legge i dati in memoria. Sia che tu legga il file zippato o il file decompresso non fa alcuna differenza sulla dimensione dei dati risultanti in memoria. Se hai 60 GB di file, read.tablenon ti salverò. In tal caso, potresti voler guardare il ffpacchetto.
Jaap,

2
@Deleet Si potrebbe utilizzare freadper leggere grandi file compressi in questo modo: fread("gunzip -c data.txt.gz", drop = c(8:13)).
Arekolek,

8

Puoi anche usare JDBC per raggiungere questo obiettivo. Creiamo un file csv di esempio.

write.table(x=mtcars, file="mtcars.csv", sep=",", row.names=F, col.names=T) # create example csv file

Scarica e salva il driver JDBC CSV da questo link: http://sourceforge.net/projects/csvjdbc/files/latest/download

> library(RJDBC)

> path.to.jdbc.driver <- "jdbc//csvjdbc-1.0-18.jar"
> drv <- JDBC("org.relique.jdbc.csv.CsvDriver", path.to.jdbc.driver)
> conn <- dbConnect(drv, sprintf("jdbc:relique:csv:%s", getwd()))

> head(dbGetQuery(conn, "select * from mtcars"), 3)
   mpg cyl disp  hp drat    wt  qsec vs am gear carb
1   21   6  160 110  3.9  2.62 16.46  0  1    4    4
2   21   6  160 110  3.9 2.875 17.02  0  1    4    4
3 22.8   4  108  93 3.85  2.32 18.61  1  1    4    1

> head(dbGetQuery(conn, "select mpg, gear from mtcars"), 3)
   MPG GEAR
1   21    4
2   21    4
3 22.8    4

0

Lo fai in questo modo:

df = read.table("file.txt", nrows=1, header=TRUE, sep="\t", stringsAsFactors=FALSE)
colClasses = as.list(apply(df, 2, class))
needCols = c("Year", "Jan", "Feb", "Mar", "Apr", "May", "Jun")
colClasses[!names(colClasses) %in% needCols] = list(NULL)
df = read.table("file.txt", header=TRUE, colClasses=colClasses, sep="\t", stringsAsFactors=FALSE)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.