Ler apenas as colunas selecionadas

134

Alguém pode me dizer como ler apenas os primeiros 6 meses (7 colunas) para cada ano dos dados abaixo, por exemplo, usando 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
StarCub
fonte
5
É duplicado de maneiras de ler apenas selecionar colunas de um arquivo no R? , Dirk menciona sobre NULLcomo classe de coluna em sua resposta .
Marek
2
@CiroSantilli 法轮功 露 宪 六四 事件 法轮功 certo, mas ... eu perguntei primeiro?
StarCub 15/05
Eu não estava implicando em um relacionamento melhor / pior. Além disso não há duplicatas local cruzadas, a rede de troca de pilha inconsistente permite-lhes, a menos que você atravessar postar-se :-)
Ciro Santilli郝海东冠状病六四事件法轮功

Respostas:

157

Digamos que os dados estejam no arquivo data.txt, você pode usar o colClassesargumento de read.table()para pular colunas. Aqui estão os dados nas 7 primeiras colunas "integer"e definimos as 6 colunas restantes para "NULL"indicar que elas devem ser puladas

> 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

Mude "integer"para um dos tipos aceitos, conforme detalhado em ?read.tabledependendo do tipo real de dados.

data.txt se parece com isso:

$ 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

e foi criado usando

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

onde datesta

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 o número de colunas não for conhecido anteriormente, a função de utilitário count.fieldslerá o arquivo e contará o número de campos em cada linha.

## 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"))
Gavin Simpson
fonte
1
@ Benjaminjam Leia as primeiras linhas do arquivo usando o argumento nrows. Em seguida, calcule quantas colunas estão usando ncol()ou, no entanto, você deseja calcular o número de colunas a serem lidas / ignoradas. Em seguida, leia o arquivo completo usando essas informações.
Gavin Simpson
1
?? Se você não sabe o número de colunas, de que outra forma vai determiná-lo sem ler um pouco para deduzir o número de colunas?
Gavin Simpson
1
@BlueMagister Obrigado pela edição e menção do count.fields()que automatiza o processo sugerido nos comentários.
precisa saber é o seguinte
1
@ LéoLéopoldHertz 준영 Não, e não tenho certeza de como isso funcionaria para as classes de linha como em um quadro de dados, enquanto cada coluna pode ser de um tipo diferente, cada linha é, por definição e, como resultado, sem restrições. Você precisará filtrar as linhas em branco, etc. na importação.
Gavin Simpson
1
@rmf você pode passar count.fields()uma conexão de texto, então, leia alguns subconjuntos de linhas usando txt <- readLines(....), então crie uma conexão com as linhas de leitura con <- textConnection(txt)e então faça count.fields(txt). Certifique-se de usar skipem count.fields()pular a linha de cabeçalho, se houver; você não pode pular linhas no arquivo usando readLines().
Gavin Simpson
82

Para ler um conjunto específico de colunas de um conjunto de dados, existem várias outras opções:

1) Com a freadpartir do data.tablepacote:

Você pode especificar as colunas desejadas com o selectparâmetro a partir freaddo data.tablepacote. Você pode especificar as colunas com um vetor de nomes ou números de colunas.

Para o exemplo de conjunto de dados:

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

Como alternativa, você pode usar o dropparâmetro para indicar quais colunas não devem ser lidas:

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

Todos resultam em:

> 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

ATUALIZAÇÃO: Quando você não deseja freadretornar uma tabela de dados , use o data.table = FALSEparâmetro-por exemplo:fread("data.txt", select = c(1:7), data.table = FALSE)

2) Com a read.csv.sqlpartir do sqldfpacote:

Outra alternativa é a read.csv.sqlfunção do sqldfpacote:

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

3) Com as read_*funções do readrpacote:

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______')

Na documentação, uma explicação para os caracteres usados ​​com col_types:

cada caractere representa uma coluna: c = caractere, i = número inteiro, n = número, d = duplo, l = lógico, D = data, T = data e hora, t = hora,? = palpite ou _ / - para pular a coluna

Jaap
fonte
freadnão suporta arquivos compactados, no entanto. Arquivos grandes geralmente são compactados.
CoderGuy123
Há uma solicitação de recurso para ativar isso fread. É importante notar que fread, provavelmente, o arquivo descompactado será muito mais rápido do que read.tableo arquivo compactado. Veja aqui um exemplo .
Jaap
Alguns arquivos não compactados são muito grandes. Por exemplo, eu estou trabalhando com 1000 arquivos de genomas. Eles podem ter 60 GB não compactados.
CoderGuy123
1
Como você provavelmente sabe, R lê os dados na memória. A leitura do arquivo compactado ou descompactado não faz diferença no tamanho dos dados resultantes na memória. Se você tiver 60 GB de arquivos, read.tablenão o salvará. Nesse caso, você pode querer olhar para o ffpacote-.
21416 Jaap
2
@Deleet Você poderia usar freadpara ler grandes arquivos compactados como este: fread("gunzip -c data.txt.gz", drop = c(8:13)).
arekolek
8

Você também pode usar o JDBC para conseguir isso. Vamos criar um arquivo csv de amostra.

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

Faça o download e salve o driver CSV JDBC neste 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
Rahul Premraj
fonte
0

Você faz assim:

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)
tedtoal
fonte