【问题标题】:How can I conditionally remove data values the day after a condition is met within an R dataframe?如何在 R 数据框中满足条件后的第二天有条件地删除数据值?
【发布时间】:2020-08-07 09:50:10
【问题描述】:

我正在处理一些环境数据,其中包括每日降雨总量。我想删除总降雨量超过零(雨 >0)的所有天以及下雨事件之后的所有天的所有“值”(标记为“NA”)。例如,如果 2018 年 1 月 3 日下雨 >0,则将 'value' 列中的所有数据标记为 'NA' 对应于 2018 年 1 月 3 日和 2018 年 1 月 4 日。很简单,但我也在摸索如何参考第二天的内容。

这是一个示例数据框:

date <- seq(as.Date("2018-1-1"), as.Date("2018-1-5"), by = 
              "1 days")
plot <- rep(c(1:4), each = 5)
treatment <- rep(c('control','treat'),each = 10)
rain <- c(0,0,2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2,0,0)
value <- (seq(1:20))
df <- data.frame(date, plot, treatment, rain,value)
df$date <- rep(date, length=nrow(df))
df



date plot treatment rain value
1  2018-01-01    1   control    0     1
2  2018-01-02    1   control    0     2
3  2018-01-03    1   control    2     3
4  2018-01-04    1   control    0     4
5  2018-01-05    1   control    0     5
6  2018-01-01    2   control    0     6
7  2018-01-02    2   control    0     7
8  2018-01-03    2   control    2     8
9  2018-01-04    2   control    0     9
10 2018-01-05    2   control    0    10
11 2018-01-01    3     treat    0    11
12 2018-01-02    3     treat    0    12
13 2018-01-03    3     treat    2    13
14 2018-01-04    3     treat    0    14
15 2018-01-05    3     treat    0    15
16 2018-01-01    4     treat    0    16
17 2018-01-02    4     treat    0    17
18 2018-01-03    4     treat    2    18
19 2018-01-04    4     treat    0    19
20 2018-01-05    4     treat    0    20

想要的结果:

            date plot treatment rain value
1  2018-01-01    1   control    0     1
2  2018-01-02    1   control    0     2
3  2018-01-03    1   control    2    NA
4  2018-01-04    1   control    0    NA
5  2018-01-05    1   control    0     5
6  2018-01-01    2   control    0     6
7  2018-01-02    2   control    0     7
8  2018-01-03    2   control    2    NA
9  2018-01-04    2   control    0    NA
10 2018-01-05    2   control    0    10
11 2018-01-01    3     treat    0    11
12 2018-01-02    3     treat    0    12
13 2018-01-03    3     treat    2    NA
14 2018-01-04    3     treat    0    NA
15 2018-01-05    3     treat    0    15
16 2018-01-01    4     treat    0    16
17 2018-01-02    4     treat    0    17
18 2018-01-03    4     treat    2    NA
19 2018-01-04    4     treat    0    NA
20 2018-01-05    4     treat    0    20

【问题讨论】:

  • 当你说“之后的所有日子”时,你真的是指“以及第二天”吗?

标签: r dataframe if-statement filter conditional-statements


【解决方案1】:

(预先说明:所有这些解决方案都依赖于提前设置的排序。外部排序并不难,可能使用dplyr::arrange 或基础order。)

使用dplyr 可以这样做:

library(dplyr)
df %>%
  group_by(plot, treatment) %>%
  mutate(value = if_else(rain > 0 | lag(rain > 0, default = FALSE), NA_integer_, value)) %>%
  ungroup()
# # A tibble: 20 x 5
#    date        plot treatment  rain value
#    <chr>      <int> <chr>     <int> <int>
#  1 2018-01-01     1 control       0     1
#  2 2018-01-02     1 control       0     2
#  3 2018-01-03     1 control       2    NA
#  4 2018-01-04     1 control       0    NA
#  5 2018-01-05     1 control       0     5
#  6 2018-01-01     2 control       0     6
#  7 2018-01-02     2 control       0     7
#  8 2018-01-03     2 control       2    NA
#  9 2018-01-04     2 control       0    NA
# 10 2018-01-05     2 control       0    10
# 11 2018-01-01     3 treat         0    11
# 12 2018-01-02     3 treat         0    12
# 13 2018-01-03     3 treat         2    NA
# 14 2018-01-04     3 treat         0    NA
# 15 2018-01-05     3 treat         0    15
# 16 2018-01-01     4 treat         0    16
# 17 2018-01-02     4 treat         0    17
# 18 2018-01-03     4 treat         2    NA
# 19 2018-01-04     4 treat         0    NA
# 20 2018-01-05     4 treat         0    20

或者,data.table

library(data.table)
DT <- as.data.table(df)
DT[rain > 0 | shift(rain > 0), value := NA, by = .(plot, treatment)]

也许在 base-R 中不太优雅:

do.call(rbind.data.frame,
        by(df, df[,c("plot", "treatment")], function(x) {
          n <- nrow(x)
          within(x, { value[ rain > 0 | c(FALSE, rain[-n] > 0) ] = NA })
        })
)

(尽管最后一个可能不会保持行的顺序相同)。


数据:

df <- read.table(header=TRUE, stringsAsFactors=FALSE, text="
date plot treatment rain value
2018-01-01    1   control    0     1
2018-01-02    1   control    0     2
2018-01-03    1   control    2     3
2018-01-04    1   control    0     4
2018-01-05    1   control    0     5
2018-01-01    2   control    0     6
2018-01-02    2   control    0     7
2018-01-03    2   control    2     8
2018-01-04    2   control    0     9
2018-01-05    2   control    0    10
2018-01-01    3     treat    0    11
2018-01-02    3     treat    0    12
2018-01-03    3     treat    2    13
2018-01-04    3     treat    0    14
2018-01-05    3     treat    0    15
2018-01-01    4     treat    0    16
2018-01-02    4     treat    0    17
2018-01-03    4     treat    2    18
2018-01-04    4     treat    0    19
2018-01-05    4     treat    0    20")

【讨论】:

    猜你喜欢
    • 2018-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多