Как избежать неявного преобразования символа при использовании применить на dataframe

При использовании apply в data.frame аргументы (неявно) преобразуются в символ. Пример:

df <- data.frame(v=1:10, t=1:10)
df <- transform(df, t2 = as.POSIXlt(t, origin = "2013-08-13"))
class(df$t2[1])
## [1] "POSIXct" "POSIXt" (correct)

а

 apply(df, 1, function(y) class(y["t2"]))
 ## [1] "character" "character" "character" "character" "character" "character"
 ## [7] "character" "character" "character" "character"

Есть ли способ избежать этого преобразования? Или мне всегда нужно преобразовать обратно через as.POSIXlt(y["t2"])?

изменить
Мой df имеет 2 временных метки (скажем, t2 и t3) и некоторые другие поля (скажем, v1, v2). Для каждой строки с заданным t2 я хочу найти строки k (например, 3) с ближайшим к t3, но ниже t2 (и тем же v1), и вернуть статистику по v2 из этих строк (например, в среднем). Я написал функцию f (t2, v1, df) и просто хотел применить ее ко всем строкам с помощью apply(df, 1, function(x) f(y["t2"], y["v1"], df). Есть ли лучший способ сделать такие вещи в R?

Ответ 1

Позвольте обернуть несколько комментариев в объяснение.

  • использование apply преобразует a data.frame в matrix. Эта означает, что будет использоваться наименее ограничивающий класс. В мере ограничительным в этом случае является символ.
  • Вы отправляете аргумент 1 в apply MARGIN. Это относится по ряду и делает вас еще хуже, поскольку вы действительно смешиваете классы теперь вместе. В этом случае вы используете apply для матриц и data.frames на вектор. Это не подходящий инструмент для работы.
  • В этом случае я бы использовал lapply или sapply, так как rmk указывает на захват классов единственный столбец t2, как показано ниже:

код:

df <- data.frame(v=1:10, t=1:10)
df <- transform(df, t2 = as.POSIXlt(t, origin = "2013-08-13"))

sapply(df[, "t2"], class)
lapply(df[, "t2"], class)

## [[1]]
## [1] "POSIXct" "POSIXt" 
## 
## [[2]]
## [1] "POSIXct" "POSIXt" 
## 
## [[3]]
## [1] "POSIXct" "POSIXt" 
## 
## .
## .
## . 
## 
## [[9]]
## [1] "POSIXct" "POSIXt" 
## 
## [[10]]
## [1] "POSIXct" "POSIXt" 

В общем случае вы выбираете семейство apply, которое соответствует заданию. Часто я лично использую цикл lapply или for для работы с определенными столбцами или подмножества столбцов, которые я хочу использовать для индексирования ([, ]), а затем перейдите к apply. Ответ на эту проблему действительно сводится к определению того, что вы хотите выполнить, спрашивая apply наиболее подходящий инструмент и продолжайте оттуда.

Могу ли я предложить этот пост в блоге в качестве отличного учебника о том, что делает в своем классе apply множество функций.

Ответ 2

Try:

sapply(df, function(y) class(y["t2"]))

$v
[1] "integer"

$t
[1] "integer"

$t2
[1] "POSIXct" "POSIXt"