Только читать выбранные столбцы

134

Может ли кто-нибудь сказать мне, как читать только первые 6 месяцев (7 столбцов) для каждого года данных ниже, например, используя 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
источник
5
Это дубликат способов чтения только выбранных столбцов из файла в R? , Дирк упомянул в своем ответе о NULLклассе столбцов .
Марек
stats.stackexchange.com/questions/16796/…
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
2
@CiroSantilli 包子 露 宪 六四 事件 法轮功 конечно, но ... я спросил первым?
StarCub
Я не имел в виду отношения лучше / хуже. Кроме того, нет межсайтовых дубликатов, несовместимая сеть обмена стеками позволяет их, если вы сами не отправляете кросс-пост :-)
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

157

Скажем, данные находятся в файле data.txt, вы можете использовать colClassesаргумент, read.table()чтобы пропустить столбцы. Здесь данные в первых 7 столбцах, "integer"и мы устанавливаем оставшиеся 6 столбцов, чтобы "NULL"указать, что они должны быть пропущены.

> 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

Измените "integer"на один из допустимых типов, как подробно описано, в ?read.tableзависимости от реального типа данных.

data.txt выглядит так:

$ 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

и был создан с использованием

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

где 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))

Если количество столбцов заранее не известно, служебная функция count.fieldsпрочитает файл и подсчитает количество полей в каждой строке.

## 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 Прочтите первую пару строк из файла, используя аргумент nrows. Затем определите, сколько столбцов используется ncol(), или, иначе, вы хотите определить количество столбцов для чтения / игнорирования. Затем прочитайте полный файл, используя эту информацию.
Гэвин Симпсон
1
?? Если вы не знаете количество столбцов, как еще вы собираетесь определить его, не читая немного, чтобы определить, сколько их?
Гэвин Симпсон
1
@BlueMagister Спасибо за редактирование и упоминание о том, count.fields()что автоматизирует процесс, который я предложил в комментариях.
Гэвин Симпсон
1
@ LéoLéopoldHertz 준영 Нет, и я не уверен, как это будет работать для классов строк, таких как фрейм данных, хотя каждый столбец может быть разного типа, каждая строка по определению и, как следствие, не ограничена. При импорте вам нужно будет отфильтровать пустые строки и т. Д.
Гэвин Симпсон
1
@rmf вы можете передать count.fields()текстовое соединение, поэтому прочитайте некоторое подмножество строк, используя txt <- readLines(....), затем создайте соединение с прочитанными в строках con <- textConnection(txt), затем сделайте count.fields(txt). Обязательно используйте skipin, count.fields()чтобы пропустить строку заголовка, если она есть; вы не можете пропустить строки в файле, используя readLines().
Гэвин Симпсон
82

Чтобы прочитать определенный набор столбцов из набора данных, есть несколько других вариантов:

1) С freadиз data.tableпакета:

Вы можете указать желаемые столбцы с selectпараметром из freadиз data.tableпакета. Вы можете указать столбцы с вектором имен столбцов или номеров столбцов.

Для примера набора данных:

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

В качестве альтернативы вы можете использовать dropпараметр, чтобы указать, какие столбцы не следует читать:

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

Все результаты в:

> 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

ОБНОВЛЕНИЕ: если вы не хотите freadвозвращать таблицу данных , используйте параметр data.table = FALSE-параметр, например:fread("data.txt", select = c(1:7), data.table = FALSE)

2) read.csv.sqlИз sqldfпакета:

Другой альтернативой является read.csv.sqlфункция из sqldfпакета:

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

3) С помощью read_*-функций из 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______')

Из документации объяснение используемых символов с col_types:

каждый символ представляет один столбец: c = символ, i = целое число, n = число, d = двойное, l = логическое, D = дата, T = дата и время, t = время,? = угадать, или _ / - чтобы пропустить столбец

Яап
источник
freadоднако не поддерживает сжатые файлы. Большие файлы обычно сжимаются.
CoderGuy123
Есть запрос функции для включения этого в fread. Стоит отметить, что freadочень вероятно, что несжатый файл read.tableбудет читать значительно быстрее, чем сжатый файл. См. Здесь пример .
Jaap
Некоторые несжатые файлы слишком велики. Например, я работаю с 1000 файлами геномов. Они могут быть 60 ГБ без сжатия.
CoderGuy123
1
Как вы, наверное, знаете, R читает данные в памяти. Независимо от того, читаете ли вы заархивированный файл или разархивированный файл, размер результирующих данных в памяти не зависит. Если у вас 60 ГБ файлов, read.tableвас не спасет. В этом случае вы можете посмотреть ffфайл -package.
Jaap
2
@Deleet Вы могли бы использовать freadдля чтения больших сжатых файлов , как это: fread("gunzip -c data.txt.gz", drop = c(8:13)).
arekolek
8

Для этого вы также можете использовать JDBC. Создадим образец файла csv.

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

Загрузите и сохраните драйвер JDBC CSV по этой ссылке: 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

Вы делаете это так:

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
источник