【问题标题】:Return last data frame column which is not NA返回不是 NA 的最后一个数据框列
【发布时间】:2017-08-29 20:09:55
【问题描述】:

我有一个数据集,其中包含多个标记为 1 或 NA 的案例。我正在尝试找出一种方法来返回每种情况下不是 NA 的最高编号邮票。

以下是一些示例数据:

PIN <- c("case1", "case2", "case3", "case4", "case5")
STAMP_1 <- c(1, 1, 1, 1, 1)
STAMP_2 <- c(NA, 1, 1, NA, 1)
STAMP_3 <- c(1, NA, 1, 1, NA)
STAMP_4 <- c(NA, NA, 1, 1, NA)
STAMP_5 <- c(1, NA, NA, 1, NA)
data <- data.frame(PIN, STAMP_1, STAMP_2, STAMP_3, STAMP_4, STAMP_5)

我想找到一种方法来返回一个包含以下列的数据框:“case1”、“case2”、“case3”、“case4”、“case5”和“STAMP_5”、“STAMP_2”,在这种情况下为“STAMP_4”、“STAMP_5”、“STAMP_2”。

【问题讨论】:

  • 为了澄清,所以对于案例 1,它会是邮票 5?情况 2,它将是邮票 2,依此类推?
  • 仅供参考,您的代码在as.data.frame 调用中抛出错误。我认为您的意思是在这里使用data.frame()cbind.data.frame()(我将您的 Q 编辑为前者),但请检查您的意图。
  • 谢谢,我就是这个意思。

标签: r dataframe na


【解决方案1】:

这是一个带有max.colis.nanames 的方法。 max.col 查找每行具有最大值的列。在这里,我们将 is.na 的值提供给它,它是 TRUE 或 FALSE,并使用 ties.method="last" 来获取最终的非 NA 值。该位置用于索引names(dat)

data.frame(PIN=dat$PIN,
           stamp=names(dat)[-1][max.col(!is.na(dat[-1]), ties.method="last")])
    PIN   stamp
1 case1 STAMP_5
2 case2 STAMP_2
3 case3 STAMP_4
4 case4 STAMP_5
5 case5 STAMP_2

如果您有一整行带有 NA,max.col 将返回该行的最终位置(静默失败?)。返回 NA 而不是该位置的一种方法是使用 NA 和求幂的技巧。在这里,我们 apply 遍历行并找到任何 NA 行,其中 any 行至少有一个非 NA 值返回 FALSE(或 0)。

data.frame(PIN=dat$PIN,
           stamp=names(dat)[-1][
                max.col(!is.na(dat[-1]), ties.method="last") * NA^!rowSums(!is.na(dat[-1]))])

在 Frank 的建议下,我从 applyapply(dat[-1], 1, function(x) all(is.na(x))) 切换到 !rowSums(!is.na(dat[-1]))。这应该比apply 快很多。

【讨论】:

  • 如果一行完全是 NA,这会返回 NA 还是...?
  • 哦,是的,我想这值得添加。
  • 不是apply,我猜还有rowSums(!is.na(dat[-1])) == 0什么的。
  • 谢谢,@Frank。当我得到分钟时,我会看看你发布的链接。 rowSums 方法肯定更好。
  • 谢谢!其他响应看起来也不错,但这成功了!不需要 NA 求幂技巧,因为所有 NA 都没有行。 Max.col 似乎是一个非常有用的函数。
【解决方案2】:

通过使用dplyrmelt(来自reshape

dat=melt(dat)
dat=na.omit(dat)
dat%>%group_by(PIN)%>%slice(n())

# A tibble: 5 x 3
# Groups:   PIN [5]
     PIN variable value
  <fctr>   <fctr> <dbl>
1  case1  STAMP_5     1
2  case2  STAMP_2     1
3  case3  STAMP_4     1
4  case4  STAMP_5     1
5  case5  STAMP_2     1

【讨论】:

  • @Jon 谢谢~乔恩
【解决方案3】:

基础R

temp = cbind(NA, data[-1])
temp = temp * col(temp)
data.frame(PIN = data$PIN,
           STAMP = names(temp)[max.col(m = replace(temp, is.na(temp), 0),
                                       ties.method = "first")])
#    PIN   STAMP
#1 case1 STAMP_5
#2 case2 STAMP_2
#3 case3 STAMP_4
#4 case4 STAMP_5
#5 case5 STAMP_2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 2022-01-26
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 2022-09-25
    相关资源
    最近更新 更多