首页 > 解决方案 > 用 NA 有条件地替换数据框中的值

问题描述

对 R 来说并不陌生,但我对更高级的 R 技术不熟悉,但我遇到了一个问题。我正在使用一个有点大的数据集(不是很大,但总共有大约 65000 行数据,包含 18 个试验)。链接在这里:https ://www.dropbox.com/s/qn6fldj9z6w21b2/wtvstyr%20%282%29.csv?dl= 0,我一直在使用它作为数据框。这是手头的任务:

我需要根据来自方向和 Y 列的信息逐个尝试有条件地替换速度值。这是我的条件:如果方向为 TRUE 并且 Y 的前 5 个值 <20,我需要将 Trial x 的所有速度值替换为 NA。如果方向是 TRUE 并且 Y 的前 5 个值不 <20,那么我只需要根据具体情况进行处理。如果方向为 FALSE 并且 Y 的前 5 个值 > 180,我需要将 Trial x 的所有速度值替换为 NA。如果方向为 FALSE 并且 Y 的前 5 个值不 > 180,那么我只需要根据具体情况进行处理。

我有以下代码使用 dplyr 来自我在这里找到的一些解决方案(主要来自dplyr 根据多个条件替换列中的 na 值):

wtvstyr <- wtvstyr %>% 
  mutate(velocity = case_when(direction == TRUE & Y<20 ~ NA_real_, TRUE ~ velocity))
wtvstyr <- wtvstyr %>%
  mutate(velocity = case_when(direction == FALSE & Y>180 ~ NA_real_, TRUE ~ velocity))

这可以根据具体情况解决我的问题。至于放弃整个试验,我很困惑。我试图用 ifelse 包裹在一个 dplyr 管道中,第一个值的索引,但我必须承认我不知道我在做什么。以下是 TRUE/<20 条件的代码,这些代码如下:在数据帧上使用 If/Else

wtvstyr %>%
  group_by(Trial) %>%
  ifelse(case_when(direction == TRUE & Y[1]<20), velocity, NA_real_)

但是,当我尝试这样做时,我得到了一个未使用的 NA 参数错误。

任何帮助,将不胜感激!如果有更好的方法来完全做到这一点(重新,屏蔽值或我不知道的其他方式),任何指导都会很棒。谢谢!

编辑

这是我的数据集的一个可重现的迷你示例:

require(tidyverse)

set.seed(80)

Trial <- c(rep(1, 40), rep(2, 40))
Y <- c(sample(0:200, 80, replace=TRUE))
Time <- c(1:80)
Direction1 <- c(rep("TRUE", 10), rep("FALSE", 10))
Direction <- c(rep(Direction1, 4))
example <- data.frame(Trial, Time, Y, Direction)

example$Y2 = example$Y 

shift <- function(x, n){
  c(x[-(seq(n))], rep(NA, n))
}

example$Y2 <- shift(example$Y2, 1)
example$velocity <- as.numeric(example$Y2) - as.numeric(example$Y)
example <- example[-c(5)]

#bit of code to remove velocities when they meet conditions I don't want:
example <- example %>% 
  mutate(velocity = case_when(Direction == TRUE & Y<20 ~ NA_real_, TRUE ~ velocity))
example <- example %>%
  mutate(velocity = case_when(Direction == FALSE & Y>180 ~ NA_real_, TRUE ~ velocity))

使用第二段代码,我可以删除我的个案值(我希望这个例子能阐明我的意思)。我仍然无法根据 Y 中的前五个值来编码某种方式来识别哪些试验需要完全丢弃。

因此,例如,在 Trial==1 和 Direction==TRUE 的数据的第一小节中,如果该小节中的前五个数据点中的任何一个 <20,我需要丢弃该部分中的所有值,而 Direction==真的。在我的原始数据集中,Direction==TRUE 和 Direction==FALSE 重复了很多次。我需要分别对待每个案例。

在我拥有的 set.seed 中,Trial==1 和 Direction==TRUE 下的前五个 Y 值是 138、40、32、192 和 99。在这里,因为没有值小于 20,所以我想保留该试验并只需删除之后满足这些条件的任何值(如上面的代码所做的那样)。但是,当 Trial==1 和 Direction==FALSE 时,我的值是 34、187、53、79 和 8。因为 187>180,我需要删除所有对应于 Trial==1 和 Direction==FALSE 的值。但是,稍后,还有另一种情况,即 Trial=1 和 Direction==FALSE。我想单独保留该案例并根据前五个值对其进行评估。如果我需要附加另一列编号,我可以将它们分开的方向重复,我可以这样做。

如果您需要更多说明,请告诉我,再次感谢您提供的任何帮助。

标签: rdataframedplyrconditional-statements

解决方案


如果我大致收集了您要查找的内容,那么最简单的方法是创建一个特殊列来保存您想要保留在其他条件之外的内容,然后手动将它们设置在case_when. 之后,您可以group_by试用和指导并设置过滤器以仅选择那些符合条件的试用/指导组(其中该组中前五个中的任何值不小于 20 或小于 180,具体取决于方向,或否则为特例)。从那里,您可以切片以获得前 5 个,但如果您也想要特殊行,我已经过滤了。

example %>%
  mutate(Direction= as.logical(Direction)) %>% 
  mutate(is.special = case_when(
    Trial== 1 & Direction == FALSE & Y == 30 ~ TRUE,
    TRUE ~ FALSE ## This is a weird convention, but TRUE just catches if nothing else evaluates TRUE and in this case, we want that to be 
  )) %>% 
  group_by(Trial, Direction) %>% 
  filter(
    is.special |
    (Direction == TRUE & !any(Y[1:5] < 20)) |
    (Direction == FALSE & !any(Y[1:5] > 180))
    ) %>% 
  filter(
    is.special | row_number() <= 5
  )

any是一个很好的功能,它将查看组的成员,看看是否有满足条件的成员。由于我否定它,您可能想使用all但我想使用您上面的标志来保持一致。


推荐阅读