Как разместить / добавить большой столбец объектов Date во фрейм данных - PullRequest
0 голосов
/ 06 августа 2011

У меня есть фрейм данных (3 строки, 12146637 строк) с именем tr.sql , который занимает 184 МБ.(он поддерживается SQL, это содержимое моего набора данных, который я прочитал через read.csv.sql)

Столбец 2 равен tr.sql $ visit_date .SQL не позволяет изначально представлять даты как объект R Date, это важно для того, как мне нужно обрабатывать данные.

Поэтому я хочу скопировать содержимое tr.sql вновый фрейм данных tr (где столбец visit_date может быть изначально представлен как Date (chron :: Date?). Поверьте, это облегчает предварительный анализ данных, а сейчас я так хочу это сделать)- Я мог бы в конечном итоге использовать собственный SQL, но, пожалуйста, не стесняйтесь пока.)


Вот мое решение (спасибо gsk и всем) + обходной путь:

tr <- data.frame(customer_id=integer(N), visit_date=integer(N), visit_spend=numeric(N))
# fix up col2's class to be Date
class(tr[,2]) <- 'Date'

затем обходной путь, копируя tr.sql -> tr кусками (скажем) N / 8, используя цикл for, так что временные элементы, участвующие в преобразовании str-> Date, не выходят из памяти, а сборщик мусора послекаждый:

для (i в 0: 7) {от <- этажа (i * N / 8) до <- этажа ((i + 1) * N / 8) -1, если (i ==7) to <- N print (c ("Копирование tr.sql $ visit_date", из, в, "...")) tr $ visit_date [из: в] <- as.Date (tr.sql $ visit_date [from: to]) gc ()} rm (tr.sql) memsize_gc () ... # только 321 Мб в конце!(во время копирования было ~ 1 ГБ) </p>


Проблема заключается в выделении, а затем копировании столбца visit_date. Вот набор данных и код, у меня возникло несколько отдельных проблем с этим, объяснение ниже:

'training.csv' looks like...
customer_id,visit_date,visit_spend 
2,2010-04-01,5.97 
2,2010-04-06,12.71 
2,2010-04-07,34.52 

и код:

# Read in as SQL (for memory-efficiency)...
library(sqldf)
tr.sql <- read.csv.sql('training.csv')
gc()
memory.size()

# Count of how many rows we are about to declare
N <- nrow(tr.sql)
# Declare a new empty data-frame with same columns as the source d.f.
# Attempt to declare N Date objects (fails due to bad qualified name for Date)
# ... does this allocate N objects the same as data.frame(colname = numeric(N)) ?
tr <- data.frame(visit_date = Date(N))
tr <- tr.sql[0,]
# Attempt to assign the column - fails
tr$visit_date <- as.Date(tr.sql$visit_date)
# Attempt to append (fails)
> tr$visit_date <- append(tr$visit_date, as.Date(tr.sql$visit_date))
Error in `$<-.data.frame`(`*tmp*`, "visit_date", value = c("14700", "14705",  : 
  replacement has 12146637 rows, data has 0
  1. Вторая строка, которая пытается объявить data.frame(visit_date = Date(N)), терпит неудачу, я не знаю правильное квалифицированное имя с пространством имен для датыобъект (пробовал chron::Date , Dates::Date? не работает)
  2. И попытка назначить и добавить не удалась.Даже не уверен, законно ли или эффективно использовать добавление в одном большом столбце фрейма данных.

Помните, что эти объекты большие, поэтому избегайте использования временных.Заранее спасибо ...

Ответы [ 3 ]

2 голосов
/ 07 августа 2011

Попробуйте убедиться, что вы используете самую последнюю версию sqldf (в настоящее время версия 0.4-1.2).

(Если вы обнаружите, что у вас недостаточно памяти, попробуйте поместить базу данных на диск, добавив аргумент dbname = tempfile() к вызову read.csv.sql. Если даже это не удастся, то оно настолько велико по отношению к доступной памяти, что вряд ли вы в любом случае мы сможем провести с ним большой анализ.)

# create test data file
Lines <- 
"customer_id,visit_date,visit_spend 
2,2010-04-01,5.97 
2,2010-04-06,12.71 
2,2010-04-07,34.52"
cat(Lines, file = "trainingtest.csv")

# read it back
library(sqldf)
DF <- read.csv.sql("trainingtest.csv", method = c("integer", "Date2", "numeric"))
0 голосов
/ 06 августа 2011

Попробуйте это:

tr <- data.frame(visit_date= as.Date(tr.sql$visit_date, origin="1970-01-01") )

Это будет успешным, если ваш формат YYYY-MM-DD или YYYY / MM / DD. Если не один из этих форматов, то опубликуйте больше деталей. Это также будет успешным, если tr.sql $ visit_date - числовой вектор, равный числу дней после начала координат. Например:

vdfrm <- data.frame(a = as.Date(c(1470, 1475, 1480), origin="1970-01-01")  )
vdfrm
           a
1 1974-01-10
2 1974-01-15
3 1974-01-20
0 голосов
/ 06 августа 2011

Мне не кажется, что у вас есть data.frame (N - вектор длины 1).Должно быть просто:

tr <- tr.sql
tr$visit_date <- as.Date(tr.sql$visit_date)

Или даже более эффективно:

tr <- data.frame(colOne = tr.sql[,1], visit_date = as.Date(tr.sql$visit_date), colThree = tr.sql[,3])

В качестве примечания, ваш заголовок гласит «добавление», но я не думаю, что вы хотите именно эту операцию.Вы расширяете data.frame, не добавляя его в конец (делая его длиннее).Концептуально это операция cbind().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...