2013-07-19 32 views
6

Tôi đang cố gắng lấy dữ liệu từ cơ sở dữ liệu PostgreSQL và kết quả cho trường dấu thời gian không nhất quán. Tôi không chắc chắn nếu tôi xử lý kết quả POSIXct đúng cách. Nếu không, tôi nghĩ rằng tôi đã tìm thấy một lỗi trong gói RPostgreSQL. Dưới đây là cách để tái tạo vấn đề:Có cách nào cụ thể để xử lý các cột dấu thời gian trong R khi kéo dữ liệu bằng cách sử dụng RPostgreSQL không?

Giả sử có một bảng trong một cơ sở dữ liệu Postgres với một lĩnh vực (chạy trong PostgreSQL):

CREATE DATABASE mydb; 
CREATE TABLE test_table 
( 
    "DateTime" timestamp without time zone NOT NULL, 
    CONSTRAINT "pk_test_table" PRIMARY KEY ("DateTime") 
) 
WITH (
    OIDS=FALSE 
); 
ALTER TABLE test_table 
    OWNER TO postgres; 

Và giả sử có một vài trăm hồ sơ. Tôi sẽ cư chúng trong R. Đây là mã:

library(RPostgreSQL) 

# Let's feed the table with some sequence of date/time values 
date_values <- as.chron(seq(10000, 10500, 1/24)) 

format.chron <- function(z) { 
    sprintf("%04.0f-%02.0f-%02.0f %02.0f:%02.0f:00", 
      as.numeric(as.character(years(z))), 
      months(z), 
      as.numeric(as.character(days(z))), 
      as.numeric(as.character(hours(z))), 
      as.numeric(as.character(minutes(z)))) 
} 

.generateInsertQuery <- function(date_values, field_name, table_name) { 
    insert_val <- paste(paste0("(", sQuote(format(date_values)), ")"), collapse=',') 
    qry   <- paste("INSERT INTO", dQuote(table_name), paste0("(", dQuote(field_name), ")"), "VALUES", insert_val) 
    qry 
} 

drv <- dbDriver('PostgreSQL') 
con <- dbConnect(drv, user='postgres', dbname='mydb') 
qry <- .generateInsertQuery(date_values, "DateTime", "test_table") 
dbSendQuery(con, qry) 

Nếu tôi cố gắng để có được các giá trị, các thành phần thời gian bị tước ra của dữ liệu kết quả

res <- dbGetQuery(con, "SELECT * FROM test_table") 
res[1:20,1] 

Lớp của kết quả, tuy nhiên, là POSIXct

class(res[,1]) 

Nếu kết quả là lấy một bản ghi tại một thời điểm, các giá trị với giờ: phút bằng 0:00 mất các thành phần thời gian:

012.
rs <- dbSendQuery(con, "SELECT \"DateTime\" FROM test_table") 
res_list <- list() 
for(i in 1:100) res_list[i] <- fetch(rs,1) 
res_list 

Như một giải pháp thay thế, tôi đang tìm nạp bản ghi kết quả 1 tại một thời điểm, sửa và gộp chúng vào một tệp dữ liệu. Nhưng điều này rất tốn thời gian, đặc biệt là đối với các tập dữ liệu lớn. Bất kỳ ý tưởng nào về lý do tại sao điều này xảy ra và cách giải quyết vấn đề này?

Cảm ơn trước!

+0

Như đã đề cập ở trên, sử dụng 'dấu thời gian với múi giờ ' trong câu lệnh' CREATE TABLE' đã thực hiện thủ thuật cho tôi.Mặc dù nó không thực sự là một phần của câu hỏi, theo kinh nghiệm của tôi, tôi đã thấy rằng 'dbWriteTable' không thích ** bất kỳ chữ cái viết hoa nào khi chỉ rõ tên bảng SQL cần ghi vào. – bibzzzz

Trả lời

3

Trước hết, dự án RPostgreSQL có danh sách gửi thư; Tôi đề nghị bạn đăng ở đó.

PostgreSQL có hai loại datetime: có và không có múi giờ. Khi tôi nhớ lại, R chỉ lập bản đồ cái sau. Tôi đã viết một số bài kiểm tra hồi quy ban đầu cho điều này (xem nguồn gói) nhưng không liên quan đến dự án về muộn. Nhưng tôi nhớ lại rằng POSIXct ánh xạ trở lại và ra đến loại datetime PostgreSQL tốt.

+0

Cảm ơn @Dirk vì đề xuất này. Trong trường hợp của tôi, tôi đang sử dụng dấu thời gian không có múi giờ và tôi vẫn đang tìm sự cố được mô tả ở trên. Tôi sẽ thử danh sách gửi thư. – JAponte

+1

Thử 'dấu thời gian với múi giờ' và xem nó có hoạt động hay không. Bạn luôn có thể sử dụng UTC làm múi giờ. –

+0

Cảm ơn bạn lần nữa vì mẹo @Dirk. Tôi đã có thể đẩy và kéo một vector dài các giá trị POSIXlt từ năm 2000 đến 2010 mà không có vấn đề gì. Vì vậy, có vẻ như dấu thời gian không có múi giờ là loại không được hỗ trợ. Điều này thậm chí còn tốt hơn, vì cách tiếp cận trước đây của tôi không rõ ràng về múi giờ, điều này có thể gây nhầm lẫn giữa người dùng dữ liệu. – JAponte

4

RPostgreSQL của dbWriteTable với bất kỳ lĩnh vực posixct sẽ tạo ra lĩnh vực cơ sở dữ liệu của loại timestamp with timezone luôn với tz +00 không có vấn đề gì múi giờ posixct nó sẽ được. Tôi tin rằng chính xác hơn sẽ là tạo ra timestamp without timezone thay thế.

Giải pháp tốt nhất cho cả dbReadTabledbWriteTable là sử dụng Sys.setenv(TZ = "UTC"). Theo tôi, nó quá phụ thuộc quá sâu bởi vì nhiều quá trình khác trong phiên R có thể yêu cầu thiết lập múi giờ thích hợp.

Phụ thuộc nhiều hơn và không phụ thuộc sâu vào việc xác định riêng dbReadTabledbWriteTable kết thúc tốt đẹp phiên bản DBI với tiền xử lý thích hợp/hậu xử lý của các loại posixct. Nhưng nó vẫn không phải là một lựa chọn nếu bạn đang phát triển mã/gói tuân thủ DBI (không chỉ liên quan đến bưu điện).

Thật tuyệt vời khi RPostgreSQL được chuyển sang github để đóng góp dễ dàng hơn.

+2

Xem dự án RPostgres mới hoạt động trên GitHub ... – hadley

Các vấn đề liên quan