【问题标题】:How to avoid implicit character conversion when using apply on dataframe在数据帧上使用应用时如何避免隐式字符转换
【发布时间】:2013-08-15 09:13:26
【问题描述】:

在 data.frame 上使用 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"]) 转换回来?

编辑
我的 df 有 2 个时间戳(比如 t2 和 t3)和一些其他字段(比如 v1、v2)。对于给定 t2 的每一行,我想找到 t3 最接近但低于 t2(以及相同的 v1)的 k(例如 3)行,并从这些行(例如平均值)返回关于 v2 的统计信息。我写了一个函数 f(t2, v1, df) 并且只想使用apply(df, 1, function(x) f(y["t2"], y["v1"], df) 将它应用于所有行。有没有更好的方法在 R 中做这些事情?

【问题讨论】:

  • 这里真正的答案是你不应该在数据框上使用apply。你想做什么?
  • 发生了转换,因为您的data.frame 被强制转换为matrix
  • 根据您的编辑,您确实有两个不同的问题 (IMO)。我会用适当的数据集、您尝试过的内容以及您想要的输出来问第二个问题(您的编辑)。
  • 我经常需要遍历数据框的行,而apply 是一种获取行和访问列的简单方法。例如。 “从每一行中取出第 1 列和第 4 列,然后对它们进行处理”。有没有更好的方法来实现这一目标?使用apply 是否被认为本质上是不好的做法,如果是,为什么?
  • @SlowLearner 改写后(谢谢)我意识到stackoverflow.com/questions/2074606/… 回答了我原来的问题

标签: r dataframe apply


【解决方案1】:

让我们把多个 cmets 总结成一个解释。

  1. 使用applydata.frame 转换为matrix。这 意味着将使用限制最少的类。至少 在这种情况下限制是字符。
  2. 您将1 提供给applyMARGIN 参数。这适用 逐行,让你的情况更糟,因为你真的在混课 现在在一起。在这种情况下,您使用的是为矩阵设计的 apply 和向量上的data.frames。这不是工作的正确工具。
  3. 在这种情况下,我会使用 lapplysapply,因为 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 系列。通常我个人使用lapplyfor 循环来处理特定列或使用索引([, ])对我想要的列进行子集化,然后继续使用apply。这个问题的答案真的归结为确定你想要完成什么,问apply是最合适的工具,然后从那里开始。

我可以提供这个blog post 作为一个很好的教程,了解不同的apply 系列函数的作用。

【讨论】:

  • 这篇博文很棒,但我认为它并没有解决我的问题。 by 应该用于数据帧,但我需要的不仅仅是按 v1 分组。
【解决方案2】:

试试:

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

$v
[1] "integer"

$t
[1] "integer"

$t2
[1] "POSIXct" "POSIXt"

【讨论】:

  • 谢谢,但我需要将我的函数应用于数据框的每一行。因此,我想要与原始数据框中一样多的行。
  • 在这种情况下,您可以使用 purrrlyr::by_row
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 2017-03-29
  • 2014-12-02
  • 1970-01-01
相关资源
最近更新 更多