我有一个名为 tr.sql 的数据框(3个字符串,12146637行),占用184Mb。 (它是由SQL支持的,它是我通过read.csv.sql读入的数据集的内容)
第2列是 tr.sql $ visit_date 。 SQL不允许将日期本地表示为R Date对象,这对于我需要处理数据的方式很重要。
因此我想将 tr.sql 的内容复制到新的数据框 tr (visit_date列可以原生地表示为Date(chron :: Date?)。相信我,这使得探索性数据分析更容易,现在这就是我想要的方式 - 我最终可能会使用原生SQL但请不要t现在狡辩。)
这是我的解决方案(感谢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 - &gt;使用for循环在(例如)N / 8的块中使用tr,以便str-&gt; Date转换中涉及的临时内容不会出现内存,并且每个后面都会进行垃圾收集:
for(i in 0:7){ 来自&lt; - floor(i * N / 8) 至&lt; - floor((i + 1)* N / 8)-1 if(i == 7) 至&lt; - N. print(c(“Copying tr.sql $ visit_date”,from,to,“......”)) tr $ visit_date [from:to]&lt; - as.Date(tr.sql $ visit_date [from:to]) GC() } RM(tr.sql) memsize_gc()......#最终只有321 Mb! (复制期间约为1Gb)
问题是分配然后复制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
data.frame(visit_date = Date(N))
的第二行失败,我不知道Date对象的命名空间的正确限定名称(尝试chron::Date , Dates::Date
?不起作用)请记住这些对象很大,所以请避免使用临时对象。 提前谢谢......
答案 0 :(得分:2)
尝试确保您使用的是最新版本的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"))
答案 1 :(得分:0)
我不认为你有一个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()
操作。
答案 2 :(得分:0)
试试这个:
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是一个等于原点后天数的数字向量,它也会成功。 E.g:
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