如何避免在使用数据框的apply函数时出现隐式字符转换

16

当在数据框上使用apply时,参数会被(隐式)转换为字符类型。例如:

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"])进行转换回去吗?
编辑 我的数据框中有2个时间戳(例如,t2和t3)和一些其他字段(例如,v1、v2)。对于每行给定的t2,我想找到k(例如3)个最接近但小于t2的t3行(并且相同的v1),并从这些行返回关于v2的统计信息(例如平均值)。我编写了一个函数f(t2,v1,df),只想应用它在所有行上使用apply(df,1,function(x) f(y["t2"],y["v1"],df)。在R中有更好的方法来做这样的事情吗?

5
实际上,你不应该在数据框上使用apply。你想要做什么? - joran
8
发生这种转换是因为您的data.frame正在被强制转换为一个matrix - Simon O'Hanlon
根据您的编辑,我认为您实际上有两个不同的问题。我建议您针对第二个问题(您的编辑)提出一个适当的数据集,说明您已经尝试过什么以及您期望的输出。 - Tyler Rinker
1
我经常需要遍历数据框的行,此时apply是一种简单的方法,可以抓取一行并访问列。例如,“从每一行中获取第1列和第4列,并对它们进行某些操作”。有没有更好的方法来实现这个目标?使用apply是否被认为是本质上不良的做法?如果是,原因是什么? - SlowLearner
1
在@SlowLearner(谢谢)的重新表述后,我意识到我的原始问题已经在https://dev59.com/cXI95IYBdhLWcg3w-C9b得到了解答。 - ang mo
显示剩余2条评论
2个回答

8
让我们将多个注释汇总成一个说明。
  1. 使用applydata.frame转换为matrix。这意味着将使用最不限制的类。在这种情况下,最不限制的是字符。
  2. 您向applyMARGIN参数提供了1。这逐行应用并使您的情况变得更糟,因为您现在真的混合了各种类。在这种情况下,您正在对向量使用设计用于矩阵和数据框的apply。这不是正确的工具。
  3. 在这种情况下,我会像rmk指出的那样使用lapplysapply来获取单个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函数族。通常我个人使用lapplyfor循环来处理特定列或使用索引([, ])子集所需的列,然后继续使用apply。解决此问题的关键是确定您想要实现什么目标,询问是否apply是最合适的工具,然后从那里开始。您可以参考这篇博客文章,了解不同apply函数族的详细教程。

2
这篇博客文章很棒,但我认为它没有解决我的问题。对于数据框,应该使用“by”,但我需要更多的内容,不仅仅是按v1分组。 - ang mo

1

尝试:

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

$v
[1] "integer"

$t
[1] "integer"

$t2
[1] "POSIXct" "POSIXt"

1
谢谢,但我需要将我的函数应用于数据帧的每一行。因此,我希望有与原始数据帧中相同数量的行。 - ang mo
在这种情况下,您可以使用purrrlyr :: by_row。 - reisner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接