R: xtable и даты

У меня есть следующие данные:

transaction <- c(1,2,3);
date <- c("2010-01-31","2010-02-28","2010-03-31");
type <- c("debit", "debit", "credit");
amount <- c(-500, -1000.97, 12500.81);
oldbalance <- c(5000, 4500, 17000.81)
evolution <- data.frame(transaction, date, type, amount, oldbalance, row.names=transaction, stringsAsFactors=FALSE);
evolution <- transform(evolution, newbalance = oldbalance + amount);
evolution

Запуск

> library(xtable)
> xtable(evolution)

работает отлично. Но если я добавлю строку

evolution$date <- as.Date(evolution$date, "%Y-%m-%d");

чтобы дать

transaction <- c(1,2,3);
date <- c("2010-01-31","2010-02-28","2010-03-31");
type <- c("debit", "debit", "credit");
amount <- c(-500, -1000.97, 12500.81);
oldbalance <- c(5000, 4500, 17000.81)
evolution <- data.frame(transaction, date, type, amount, oldbalance, row.names=transaction, stringsAsFactors=FALSE);
evolution$date <- as.Date(evolution$date, "%Y-%m-%d");
evolution <- transform(evolution, newbalance = oldbalance + amount);
evolution

тогда запуск xtable дает

xtable (эволюция)     Ошибка в Math.Date(x + ifelse (x == 0, 1, 0)):   abs не определен для объектов Date

Но в этом случае полезно использовать xtable, чтобы сделать некоторую фильтрацию дат

evolution$date <- as.Date(evolution$date, "%Y-%m-%d")
startdate <-as.Date("2010-02-01");
enddate <-as.Date("2010-03-30");
newdate <-evolution[which (evolution$date >= startdate & evolution$date <= enddate),]
newdate


> newdate
  transaction       date  type   amount oldbalance newbalance
2           2 2010-02-28 debit -1000.97       4500    3499.03
> xtable(newdate)
Error in Math.Date(x + ifelse(x == 0, 1, 0)) :
  abs not defined for Date objects

Ответ 1

Это, возможно, ошибка в xtable - вы можете сообщить об этом сопровождающему.

Временная работа - вызов as.character() для классов, которые xtable неверно интерпретируют (кроме "Date", я могу думать о "POSIXt", но могут быть и другие), например:

xtable <- function(x, ...) {
   for (i in which(sapply(x, function(y) !all(is.na(match(c("POSIXt","Date"),class(y))))))) x[[i]] <- as.character(x[[i]])
   xtable::xtable(x, ...)
}

Ответ 2

Похоже, что xtable не всегда хорошо сочетается с столбцами класса Date. (У него есть методы zoo и ts, но это может не помочь, если у вас есть один столбец дат/времени в фрейме данных, как принуждение к зоопарку, похоже, изменяет имена столбцов в результирующей таблице.) Несколько примечаний:

  • Ошибка фактически вызывается print.xtable, (not xtable.data.frame), которая вызывается по умолчанию, чтобы отображать результаты xtable в консоли. Таким образом, вы обнаружите, что если вы сохранили результаты xtable в переменной, вы не получите никакой ошибки, но затем, когда вы попытаетесь выполнить print, появится та же ошибка.

  • Поскольку вы мудро сохранили свои даты в формате YYYY-MM-DD, преобразование их в объекты Date фактически не требуется для использования упорядоченных выборов, поскольку они будут сортироваться должным образом в качестве символов. Таким образом, вы могли бы просто уйти, просто сохраняя их как символы.

  • В случаях с более сложными объектами даты и времени вы можете выполнить подмножество сначала, а затем преобразовать эти столбцы в символы. Или создайте обертку для xtable.data.frame и добавьте строки в начале,

    dates <- sapply(x,FUN = function(x){class(x) == "Date"})
    x[,dates] <- as.character(x[,dates])
    

    проверка класса Date или любого другого класса, с которым вы имеете дело.

  • IMHO, xtable.data.frame должен, вероятно, проверять даты и, возможно, другие классы POSIX и преобразовывать их в строки. Это может быть простое изменение, и, возможно, стоит связаться с автором пакета.

  • Наконец, точки с запятой в качестве ограничителей строк не нужны.:) Привычка с другого языка?

Ответ 3

Как сопровождающий xtable, я хотел бы заявить о том, что я считаю истинной позицией в отношении дат в xtable.

Это на самом деле не ошибка, но отсутствие функции, которая может показаться вам желательной.

Проблема в том, что xtable может работать только с тремя разными классами столбцов: логический; персонаж; и числовой. Если вы попытаетесь отправить таблицу с классом столбца Date, он не сможет справиться с этим. Соответствующий код представляет собой набор методов xtable, наиболее важными из которых являются xtable.data.frame и xtable.matrix.

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

Можно было бы добавить код, чтобы разрешить столбцы класса Date, но я не хочу этого делать.

Во-первых, существует легкий обходной путь (по крайней мере, для прямого кода R, я не могу сказать, для приложений Shiny), который заключается в замене любого столбца Date на символьный столбец:

Во-вторых, чтобы разрешить столбцы класса Date, потребуется добавить аргумент к методам xtable и xtable (которых в настоящее время их 31), а также к xtableFtable и xtableList. Это чревато проблемами из-за большого количества обратных зависимостей для xtable. (Не в счет, но если вы посмотрите на xtable в CRAN, вы увидите стек зависимостей, импорт и предложения.) Я собираюсь разбить некоторые пакеты, может быть, много пакетов, если я сделаю такое изменение. Обратная совместимость - серьезная проблема с xtable.

Зачем нужен дополнительный аргумент? Потому что конечным результатом использования xtable, или более того, до точки print.xtable, является строка символов. То, как обрабатываются столбцы фрейма данных, матрицы или другой структуры, представленной в xtable, определяется сначала тем, как они классифицируются (логические, символьные или числовые), затем аргументами align, digits и display, которые могут быть векторами, которые позволяют для разной обработки разных колонн. Таким образом, если даты должны быть разрешены, вам понадобится дополнительный аргумент, чтобы указать, как они будут форматироваться, потому что в какой-то момент их необходимо преобразовать в символ для получения окончательного результата таблицы.