【问题标题】:Replace NA in a POSIXct serie by adjacent values用相邻值替换 POSIXct 系列中的 NA
【发布时间】:2020-02-20 15:20:25
【问题描述】:

我有一个这样的数据框(但行数更多):

  individ_id           date_time               begin           end
1: NOS_4214433 2017-11-22 09:01:49 2017-11-21 11:54:59 2017-11-22 09:07:27
2: NOS_4214433 2017-11-22 09:06:49 2017-11-21 11:54:59 2017-11-22 09:07:27
3: NOS_4214433 2017-11-22 09:11:49                <NA>                <NA>
4: NOS_4214433 2017-11-22 09:16:49                <NA>                <NA>
5: NOS_4214433 2018-01-24 12:12:18 2018-01-24 12:08:28 2018-01-25 09:33:10

我想用“开始”列的第一个 NA date_time 值和“结束”列的最后一个 date_time NA 值填充开始和结束列中的 NA,如下所示:

    individ_id           date_time               begin                 end
1: NOS_4214433 2017-11-22 09:01:49 2017-11-21 11:54:59 2017-11-22 09:07:27
2: NOS_4214433 2017-11-22 09:06:49 2017-11-21 11:54:59 2017-11-22 09:07:27
3: NOS_4214433 2017-11-22 09:11:49 2017-11-22 09:11:49 2017-11-22 09:16:49
4: NOS_4214433 2017-11-22 09:16:49 2017-11-22 09:11:49 2017-11-22 09:16:49
5: NOS_4214433 2018-01-24 12:12:18 2018-01-24 12:08:28 2018-01-25 09:33:10

所有的日期时间数据都是 POSIX 格式,我想保持这种格式。 有没有人想办法解决这个问题?

【问题讨论】:

  • 所以你的 NA 总是成对出现?

标签: r na missing-data fill posixct


【解决方案1】:

我相信这可以解决您的问题:

library(tidyr)

na_inds_begin <- as.numeric((is.na(df$begin)))
na_inds_end <- as.numeric((is.na(df$end)))

na_diffs_lead <- c(0, diff(na_inds_begin))
na_diffs_lag <- c(diff(na_inds_end), 0)

first_nas <- na_inds_begin == 1 & na_diffs_lead > 0
first_nas[1] <- na_inds_begin[1] == 1

last_nas <- na_inds_end == 1 & na_diffs_lag < 0 
last_nas[length(last_nas)] <- na_inds_end[length(na_inds_end)] == 1

df$begin[first_nas] <- df$date_time[first_nas]
df$end[last_nas] <- df$date_time[last_nas]

df$begin[first_nas] <- df$date_time[first_nas]
df$end[last_nas] <- df$date_time[last_nas]

df <-
  df %>%
  fill(begin, .direction = "down") %>%
  fill(end, .direction = "up")

首先,我们在begin 中找到每组NAs 中的第一个NA,在end 中找到每组NAs 中的最后一个NA。我们还需要处理begin 中的第一个元素或end 中的最后一个元素是NA 的情况。然后我们只用所需的替换替换那些元素。最后,我们将每个组的其余部分向下填充begin,向上填充end

这是结果:

> df
# A tibble: 5 x 4
  individ_id  date_time           begin               end                
  <chr>       <dttm>              <dttm>              <dttm>             
1 NOS_4214433 2017-11-22 09:01:49 2017-11-21 11:54:59 2017-11-22 09:07:27
2 NOS_4214433 2017-11-22 09:06:49 2017-11-21 11:54:59 2017-11-22 09:07:27
3 NOS_4214433 2017-11-22 09:11:49 2017-11-22 09:11:49 2017-11-22 09:16:49
4 NOS_4214433 2017-11-22 09:16:49 2017-11-22 09:11:49 2017-11-22 09:16:49
5 NOS_4214433 2018-01-24 12:12:18 2018-01-24 12:08:28 2018-01-25 09:33:10

编辑:我更新了示例代码以适应beginend 具有不同NA 索引或第一个/最后一个元素是NA 的情况。

【讨论】:

  • 这很好用,除非 NA 间隙位于数据帧的开头或结尾。当第一个位置有 NA 时,开始列不填充,当 NA 在最后一个位置时,它是未填充的结束列。
  • 我已经通过在填充函数之前添加这些行来解决这个问题:if(is.na(mydatan$begin[1])){ mydatan$begin[1] &lt;- mydatan$date_time[1] } if(is.na(mydatan$end[nrow(mydatan)])){ mydatan$end[nrow(mydatan)] &lt;- mydatan$date_time[nrow(mydatan)] }
  • 另一种方法是直接使用na_inds_beginna_inds_end,因为我们已经有了它们。我将其纳入解决方案。如果您使用了答案,请接受! :)
猜你喜欢
  • 2017-04-22
  • 2015-07-28
  • 2021-09-22
  • 2013-03-15
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多