2013-10-04 3 views
1

Рассмотрим следующий R-код, который заменяет значения в одном столбце кадра данных с набором значений POSIXct:Замена значений столбцов с объектом POSIXlt

foo <- as.data.frame(list(bar=rep(5,5))) 
bar <- as.POSIXct(rep(5,5), origin="1970-1-1", tz="c") 
foo[,1] <- bar 

Мой вопрос: почему же операцию строя, когда Я пытаюсь использовать POSIXlt вместо этого? Например:

foo <- as.data.frame(list(bar=rep(5,5))) 
bar <- as.POSIXlt(rep(5,5), origin="1970-1-1", tz="c") 
foo[,1] <- bar 
Warning message: 
    In `[<-.data.frame`(`*tmp*`, , 1, value = list(sec = c(5, 5, 5, : 
    provided 9 variables to replace 1 variables 

Кроме того, если я сошлюсь на колонку по имени, а не по индексу, то же самое назначение работает просто отлично:

foo$bar <- bar 
foo <- as.data.frame(list(bar=rep(5,5))) 
bar <- as.POSIXlt(rep(5,5), origin="1970-1-1", tz="c") 
foo$bar <- bar 

Что мне не хватает?

+1

Я получаю предупреждение о том, что часовой пояс «c» неизвестен в моей системе. –

+0

Роман: У меня нет предупреждения. «c» следует ссылаться на текущий часовой пояс. Наверное, вы могли бы указать UCT вместо этого? или ваш часовой пояс? – Daniel

ответ

4

От help("[.data.frame"):

Для [значение замена может быть списком: каждый элемент списка используется для замены (часть) на одну колонку, рециркуляции список по мере необходимости.

Так что вы можете сделать что-то вроде этого:

df <- data.frame(a=1:2) 
df[,2:3] <- list(3:4, 5:6) 
# a V2 V3 
#1 1 3 5 
#2 2 4 6 

Однако это приводит к предупреждению:

df[,4] <- list(7, 8) 
# Warning message: 
# In `[<-.data.frame`(`*tmp*`, , 4, value = list(7, 8)) : 
# provided 2 variables to replace 1 variables 
# a V2 V3 V4 
# 1 1 3 5 7 
# 2 2 4 6 7 

Теперь POSIXlt объект представляет собой список с 9 элементов:

unclass(rep(as.POSIXlt(Sys.time()), 2)) 
# $sec 
# [1] 1.958244 1.958244 
# 
# $min 
# [1] 54 54 
# 
# $hour 
# [1] 10 10 
# 
# $mday 
# [1] 4 4 
# 
# $mon 
# [1] 9 9 
# 
# $year 
# [1] 113 113 
# 
# $wday 
# [1] 5 5 
# 
# $yday 
# [1] 276 276 
# 
# $isdst 
# [1] 1 1 
# 
# attr(,"tzone") 
# [1] ""  "CET" "CEST" 

Присвоение этого списка одной колонке с использованием [<-.data.frame дает предупреждение, которое вы наблюдаете.

Потенциальные решения проблемы просты:

  • Использование POSIXct и избежать POSIXlt. Единственной причиной использования последнего является необходимость извлечь некоторые из компонентов списка, что не так часто (и вы всегда можете принуждать к POSIXlt, например, внутри функции для округления значений времени).
  • Использование $<-.data.frame. Это часто громоздко вне интерактивного использования.
  • Оберните POSIXlt объект в list для назначения: df[,1] <- list(POSIXlt_object).
+0

Очень всеобъемлющий. Благодаря! – Daniel

1

Похоже, что POSIXlt объекты - это списки, в том числе 9 записей.

unlist(as.POSIXlt(5, origin="1970-1-1")) 
sec min hour mday mon year wday yday isdst 
    5  0  1  1  0 70  4  0  0 

unlist(as.POSIXct(5, origin="1970-1-1")) 
[1] "1970-01-01 00:00:05 CET" 

Видимо отнесение к data.frame терпит неудачу, потому что POSIXlt объект в списке нет.

foo <- as.data.frame(list(bar=rep(5,5))) 
bar <- as.POSIXlt(rep(5,5), origin="1970-1-1", tz="") 
foo[,1] <- bar # this fails 
foo[,1:9] <- bar # this works 

С другой стороны, назначение списка работает.

foo <- as.data.frame(list(bar=rep(5,5))) 
bar <- as.POSIXlt(rep(5,5), origin="1970-1-1", tz="") 
foo[[1]] <- bar # or foo$bar <- bar 
Смежные вопросы