Lire uniquement les colonnes sélectionnées

134

Quelqu'un peut-il me dire comment lire uniquement les 6 premiers mois (7 colonnes) pour chaque année des données ci-dessous, par exemple en utilisant 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
la source
5
C'est un double des moyens de lire uniquement les colonnes sélectionnées d'un fichier dans R? , Dirk mentionne NULLcomme classe de colonne dans sa réponse .
Marek
stats.stackexchange.com/questions/16796/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
2
@CiroSantilli 包子 露 宪 六四 事件 法轮功 bien sûr mais ... j'ai demandé en premier?
StarCub
Je n'impliquais pas une relation meilleure / pire. De plus, il n'y a pas de doublons inter-sites, le réseau d'échange de pile incohérent le permet, sauf si vous vous
croisez

Réponses:

157

Supposons que les données soient dans un fichier data.txt, vous pouvez utiliser l' colClassesargument de read.table()pour ignorer les colonnes. Ici, les données des 7 premières colonnes sont "integer"et nous définissons les 6 colonnes restantes pour "NULL"indiquer qu'elles doivent être ignorées

> 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

Passez "integer"à l'un des types acceptés comme détaillé dans en ?read.tablefonction du type réel de données.

data.txt ressemble à ça:

$ 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

et a été créé en utilisant

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

datest

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

Si le nombre de colonnes n'est pas connu à l'avance, la fonction utilitaire count.fieldslira le fichier et comptera le nombre de champs dans chaque ligne.

## 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
la source
1
@Benjamin Lit les deux premières lignes du fichier en utilisant l'argument nrows. Ensuite, déterminez le nombre de colonnes utilisées ncol(), ou quelle que soit la manière dont vous souhaitez calculer le nombre de colonnes à lire / ignorer. Ensuite, lisez le fichier complet en utilisant ces informations.
Gavin Simpson
1
?? Si vous ne connaissez pas le nombre de colonnes, comment allez-vous le déterminer autrement sans en lire un peu pour en déduire le nombre?
Gavin Simpson
1
@BlueMagister Merci pour l'édition et la mention du count.fields()qui automatise le processus que j'ai suggéré dans les commentaires.
Gavin Simpson
1
@ LéoLéopoldHertz 준영 Non, et je ne sais pas comment une telle chose fonctionnerait pour des classes de lignes comme dans un bloc de données, alors que chaque colonne peut être d'un type différent, chaque ligne est, par définition et par conséquent, sans contrainte. Vous devrez filtrer les lignes vides, etc. lors de l'importation.
Gavin Simpson
1
@rmf vous pouvez passer count.fields()une connexion texte, alors, lisez un sous-ensemble des lignes à l'aide de txt <- readLines(....), puis créez une connexion aux lignes de lecture con <- textConnection(txt), puis faites count.fields(txt). Veillez à utiliser skipin count.fields()pour ignorer la ligne d'en-tête s'il y en a une; vous ne pouvez pas sauter de lignes dans le fichier avec readLines().
Gavin Simpson
82

Pour lire un ensemble spécifique de colonnes à partir d'un ensemble de données vous, il existe plusieurs autres options:

1) Avec freaddu data.table-package:

Vous pouvez spécifier les colonnes souhaitées avec le selectparamètre à freadpartir du data.tablepackage. Vous pouvez spécifier les colonnes avec un vecteur de noms de colonnes ou de numéros de colonnes.

Pour l'exemple d'ensemble de données:

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

Vous pouvez également utiliser le dropparamètre pour indiquer quelles colonnes ne doivent pas être lues:

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

Tous aboutissent à:

> 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

MISE À JOUR: Lorsque vous ne voulez freadpas renvoyer une table data.table , utilisez le data.table = FALSEparamètre -paramètre, par exemple:fread("data.txt", select = c(1:7), data.table = FALSE)

2) Avec read.csv.sqldu sqldf-package:

Une autre alternative est la read.csv.sqlfonction du sqldfpackage:

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

3) Avec les read_*-fonctions du -package readr:

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

Dans la documentation, une explication des caractères utilisés avec col_types:

chaque caractère représente une colonne: c = caractère, i = entier, n = nombre, d = double, l = logique, D = date, T = date heure, t = heure,? = guess, ou _ / - pour sauter la colonne

Jaap
la source
freadne prend cependant pas en charge les fichiers compressés. Les fichiers volumineux sont généralement compressés.
CoderGuy123
Il y a une demande de fonctionnalité pour l'activer dans fread. Il convient de noter que la freadlecture du fichier non compressé sera très probablement beaucoup plus rapide que celle read.tabledu fichier compressé. Voir ici pour un exemple .
Jaap
Certains fichiers non compressés sont trop volumineux. Par exemple, je travaille avec 1000 fichiers Genomes. Ils peuvent être de 60 Go non compressés.
CoderGuy123
1
Comme vous le savez probablement, R lit les données en mémoire. Que vous lisiez le fichier compressé ou le fichier décompressé ne fait aucune différence sur la taille des données résultantes en mémoire. Si vous avez 60 Go de fichiers, read.tablene vous sauvera pas. Dans ce cas, vous voudrez peut-être regarder le ff-package.
Jaap
2
@Deleet Vous pouvez utiliser freadpour lire les fichiers compressés volumineux comme celui - ci: fread("gunzip -c data.txt.gz", drop = c(8:13)).
arekolek
8

Vous pouvez également utiliser JDBC pour y parvenir. Créons un exemple de fichier csv.

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

Téléchargez et enregistrez le pilote CSV JDBC à partir de ce lien: 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
la source
0

Vous le faites comme ceci:

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
la source