【问题标题】:Using apply() but getting class list answer使用 apply() 但获得类列表答案
【发布时间】:2018-06-04 13:35:11
【问题描述】:

我在data.frame 中有一系列列,我想获取其中的最后一个值,不包括任何 NA。我用来完成这项工作的功能是

    last_value <- function(x) tail(x[!is.na(x)], 1)

我正在使用apply() 为每个观察(按行)跨 13 列执行此函数。

    df$LastVal<-apply(df[,c(116, 561, 1006, 1451, 1896, 2341, 2786, 3231, 
    3676, 4121, 4566, 5011, 5456)], 1, FUN=last_value)

我的问题是输出作为 5336(总观察值)的列表出现,而不仅仅是按行显示最后一个值的向量。答案似乎在那里,但又以列表的形式出现。我以前用过这个功能,效果很好。当我str() 我的列时,它们都是整数。 如果没有值而只有 NA,这个函数会被绊倒吗?

我应该补充一点,当我 unlist() 新变量时,我收到一条错误消息,提示“替换有 4649 行,数据有 5336”,所以我认为这可能与 NA 有关。

【问题讨论】:

  • 如果没有值而只有 NA,这个函数会不会出错? 可以,我刚试过,它确实返回了一个列表。
  • 如果 all(is.na(x))TRUE 从你的函数返回 NA
  • @RuiBarradas 我怎样才能重新编写函数来避免这种情况?我无法取出那些具有 NA 的行,因为它们对于另一次分析至关重要。

标签: r function apply tail


【解决方案1】:

首先,您需要查看函数 last_value 的输出是什么,因为您已经使用一行 NA 值定义了它。

last_value <- function(x) tail(x[!is.na(x)], 1)

df <- matrix(1:24, 4)
df[2, ] <- NA
df <- as.data.frame(df)
apply(df, 1, last_value)
#[[1]]
#V6 
#21 
#
#[[2]]
#named integer(0)
#
#[[3]]
#V6 
#23 
#
#[[4]]
#V6 
#24

问题是这个列表的第二个成员的长度为零。这意味着unlist 不会解决问题。
您必须测试长度为零的值。

last_value <- function(x) {
  y <- tail(x[!is.na(x)], 1)
  if(length(y) == 0) NA else y
}
apply(df, 1, last_value)
#[1] 21 NA 23 24

【讨论】:

  • 完美!谢谢@RuiBarradas
【解决方案2】:

您可以将您的功能包含在选择中。

示例

df <- as.data.frame(matrix(1:12, 3, 4))
> df
  V1 V2 V3 V4
1  1  4  7 10
2  2  5  8 11
3  3  6  9 12

last_value <- function(x) tail(x[!is.na(x)], 1)

> df[, last_value(c(3, 4))]  # selects last column
[1] 10 11 12

使用NA 进行测试。

df[2, 4] <- NA
> df[, last_value(c(3, 4))]
[1] 10 NA 12

如果您需要apply() 方法,请使用@Rui Barradas 的详细解释答案。如果您依赖速度,请考虑两种解决方案的基准:

Unit: microseconds
                      expr     min       lq      mean  median       uq     max neval cld
  apply(df, 1, last_value) 166.095 172.6005 182.09241 177.449 188.2925 257.179   100   b
 df[, last_value(c(3, 4))]  32.147  33.4230  36.12764  34.699  35.5920 131.396   100  a 

恰如其分——按列使用sapply()

> sapply(df[, c(3, 4)], FUN=last_value)
V3 V4 
 9 12 

【讨论】:

  • 为了完整起见sapply 有时也会返回列表。 IMO,如果您想享受应用系列,请坚持lapply,有时是tapply,如果您获得列表,请使用do.call(cbind,mylappy_output)rbind 而不是cbind
  • 嗨@jaySf,感谢您的回答,但这并不是我想要做的。这应该针对您的三个观察结果中的每一个,并生成一个向量,结果为 10、11、12。
猜你喜欢
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
  • 2019-08-19
  • 1970-01-01
  • 2022-10-17
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
相关资源
最近更新 更多