Сохраните список в data.table в csv и загрузите его обратно (R) - PullRequest
0 голосов
/ 13 января 2020

У меня есть data.table, который содержит столбец списка. Это таблица, которую мне нужно писать для каждой сессии, поэтому после повторного открытия приложения я могу go вернуться в самое последнее состояние.

Таблица выглядит следующим образом:

data.table(`ID Universal` = character(), StartDate = as.Date(character()), EndDate = as.Date(character()), 
                      BOX = character(), `Days in Period` = numeric(), 
                      `Workdays in Period` = integer(), `Present Workdays in Period` = integer(), 
                      `Days not present in Period` = list())

Написание части, которую я пытался решить с помощью strsplit:

dt.absent <- data.table(do.call("rbind", strsplit(as.character(global$dt.requests$`Days not present in Period`), ",")))
dt.req_csv <- cbind(global$dt.requests[, -8], dt.absent)
write.csv(dt.req_csv, "Requests.csv", row.names = FALSE)

Этот процесс, кажется, работает как задумано (также открыт для альтернатив), но часть загрузки не может работать. Я хочу загрузить CSV, чтобы он выглядел так же, как оригинальный data.table (я использую формат даты YYYY-mm-dd по умолчанию)

Ответы [ 2 ]

2 голосов
/ 13 января 2020

Затем вы должны сохранить данные как файл rds, а не как файл csv. Когда вы используете fread, вы теряете факторные переменные, а иногда и даты.

Просто сохраните его как файл RDS и перезагрузите его вот так.

saveRDS(object, "file.rds")
object <- readRDS("file.rds")
1 голос
/ 13 января 2020

Поскольку мы не видим фактическое содержание data.table, немного сложно рассуждать о том, что именно вы подразумеваете под , «выглядит как» . Я предполагаю, что это POSIXt / Date вещь во время чтения. Вот обходной путь, использующий read.csv(..., colClasses=).

### create a file
write.csv(data.table(rn=100L, nowdt=Sys.Date(), nowpsx=Sys.time()), "~/StackOverflow/WietsedeVries.csv", row.names=F)
readLines("~/StackOverflow/WietsedeVries.csv")
# [1] "\"rn\",\"nowdt\",\"nowpsx\""        "100,2020-01-13,2020-01-13 08:55:56"

(Обратите внимание, что на POSIXt влияет options(digits.secs).)

Чтение в:

str(read.csv("~/StackOverflow/WietsedeVries.csv"))
# 'data.frame': 1 obs. of  3 variables:
#  $ rn    : int 100
#  $ nowdt : Factor w/ 1 level "2020-01-13": 1
#  $ nowpsx: Factor w/ 1 level "2020-01-13 08:55:56": 1
str(read.csv("~/StackOverflow/WietsedeVries.csv", colClasses=c(nowdt="Date", nowpsx="POSIXct")))
# 'data.frame': 1 obs. of  3 variables:
#  $ rn    : int 100
#  $ nowdt : Date, format: "2020-01-13"
#  $ nowpsx: POSIXct, format: "2020-01-13 08:55:56"

(я считаю, что data.table::fread пока не поддерживает функциональность для POSIXct или Date.)


Примечания:

  • Как вы можете как видно из вывода readLines, отметка времени не содержит никакой информации о часовом поясе. Если вы просто беспокоитесь о датах, то это не проблема. Если вы всегда всегда всегда совершаете сделку в одном и том же часовом поясе (например, все "UT C"), то это не проблема. Однако для всего остального вам необходимо добавить еще немного кода для кодирования информации о часовом поясе. Это уменьшает простоту использования colClasses= (поскольку будет использоваться as.POSIXct без format="...", поэтому вам придется обрабатывать столбец вручную после read.csv(..., colClasses=c(nowpsx="character"))).

  • Поскольку вы говорите «писать после каждого сеанса» , вы можете вместо этого использовать какую-либо базу данных. Если вы хотите сохранить простоту, то RSQLite все еще просто требует один внешний файл в файловой системе, и вы можете сделать немного больше с набором данных на основе базы данных, чем с CSV. Хотя сам по себе SQLite не имеет идеальных классов времени / даты, я считаю, что комбинация DBI / RSQLite прекрасно справляется с задачей, которая вам нужна в большинстве случаев. В этой заметке вы, вероятно, захотите включить по крайней мере еще два столбца: некоторый уникальный идентификатор (возможно, увеличивающееся целое число) и «созданную» временную метку, просто для ведения записей, если ничего больше.

...