未分明数据并填充零值以从R中的状态变化中获取当前状态



我已经搜索了网络以寻求解决方案,但是,无法找到该特定主题的答案。

我有一个数据框,显示了19个不同单位的数据,每个单位都有2个部门。这些部门可以在不同的州(州1-5(,并且必须始终处于州。

数据本身看起来像这样:

Time        department      fromState   toState Date
46051.41923 unit36:depr2    4           5       2017-05-22 10:47
46077.33833 unit37:depr1    3           4       2017-05-22 10:47
47057.31889 unit31:depr2    2           3       2017-05-22 11:04
47062.31889 unit31:depr1    3           6       2017-05-22 11:04

数据显示了每个部门在国家变更之前(从州(发生的状态,并将在州变更(Tostate(之后进行。

我希望拥有的是:

Date               unit36:depr2   unit37:depr1   unit31:depr2   unit31:depr1
2017-05-22 10:47    5              4              2              3
2017-05-22 11:04    5              4              3              6

这是这样,我可以始终看到所有单位都在哪些状态。如您所见,我已经将Fromstate和Tostate手动合并为列中,并将其与DEPR名称合并。我还删除了重复的日期值。时间列用于制作日期列,并且也已删除。

有什么办法可以以非手术方式执行此操作?

这是使用整形函数的另一种策略。首先,您的数据

library(tidyverse)
dd <- read_csv("Time,department,fromState,toState,Date
46051.41923,unit36:depr2,4,5,2017-05-22 10:47
46077.33833,unit37:depr1,3,4,2017-05-22 10:47
47057.31889,unit31:depr2,2,3,2017-05-22 11:04
47062.31889,unit31:depr1,3,6,2017-05-22 11:04")

现在我得到了每个部门的第一个日期

start <- dd %>% 
  group_by(department) %>% 
  summarize(state=first(fromState)) %>% 
  spread(department, state)

现在每个日期都得到所有当前状态

changes <- dd %>% 
  arrange(Date) %>% 
  select(Date, department, toState) %>% 
  split(.$Date)  %>% 
  map(spread, department, toState)

然后我使用 accumulate来"重播"每个日期的更改。

alt_list_modify <- function(x, y) list_modify(x, !!!y)
final <- accumulate(changes, alt_list_modify, .init = start) %>% 
  tail(-1) %>% bind_rows()

这返回所需的结果

# A tibble: 2 x 5
  `unit31:depr1` `unit31:depr2` `unit36:depr2` `unit37:depr1`                Date
           <int>          <int>          <int>          <int>              <dttm>
1              3              2              5              4 2017-05-22 10:47:00
2              6              3              5              4 2017-05-22 11:04:00

我建议您以不同的方式查看数据。我认为您应该考虑"初始状态",然后在发生时调用更改,而不是"从"one_answers"。使用您的数据(在此处添加" X"以轻松处理read.table(text=...),请使用您自己的数据(:

x <- read.table(text='Time        department      fromState   toState Date x
46051.41923 unit36:depr2    4           5       2017-05-22 10:47
46077.33833 unit37:depr1    3           4       2017-05-22 10:47
47057.31889 unit31:depr2    2           3       2017-05-22 11:04
47062.31889 unit31:depr1    3           6       2017-05-22 11:04', header=TRUE, stringsAsFactors=FALSE)
x$Date <- as.POSIXct(paste(x$Date, x$x))
x$x <- NULL

我将使用两个库为此,因为我认为它们在这里很合适并且易于阅读。我相信有人可以建议data.table(可能更快(和base-r(不是包装依赖性(解决方案。

library(dplyr)
library(tidyr)

第一件事是确定所有部门的起始状态。(0日期只是"在发生其他任何事情之前"。(

initial_state <- x %>%
  arrange(Date) %>%
  group_by(department) %>%
  summarize(
    date = as.POSIXct(0, origin='1970-01-01'),
    state = fromState[1]
  )
initial_state
# # A tibble: 4 × 3
#     department       date state
#          <chr>     <dttm> <int>
# 1 unit31:depr1 1970-01-01     3
# 2 unit31:depr2 1970-01-01     2
# 3 unit36:depr2 1970-01-01     4
# 4 unit37:depr1 1970-01-01     3

现在记录情况时发生变化:

transitions <- select(x, department, date = Date, state = toState)
transitions
#     department                date state
# 1 unit36:depr2 2017-05-22 10:47:00     5
# 2 unit37:depr1 2017-05-22 10:47:00     4
# 3 unit31:depr2 2017-05-22 11:04:00     3
# 4 unit31:depr1 2017-05-22 11:04:00     6

下一步是进行不分散:

bind_rows(initial_state, transitions) %>%
  spread(department, state)
# # A tibble: 3 × 5
#                  date `unit31:depr1` `unit31:depr2` `unit36:depr2` `unit37:depr1`
# *              <dttm>          <int>          <int>          <int>          <int>
# 1 1970-01-01 00:00:00              3              2              4              3
# 2 2017-05-22 10:47:00             NA             NA              5              4
# 3 2017-05-22 11:04:00              6              3             NA             NA

...意识到 NA表示"这一天对这一天没有发生任何事情,因此从上一个非NA行中出发" 。幸运的是,zoo软件包中有一个功能可以做到这一点:

na.locf软件包:Zoo R Documentation

最后一个观察

描述:

替换每个" NA"用最新的" NA"的通用功能

library(zoo) # for clarity, not strictly requires since I use '::' here
bind_rows(initial_state, transitions) %>%
  spread(department, state) %>%
  mutate_all(zoo::na.locf) %>%
  filter(date > 0) # since I no longer need the "0" date
# # A tibble: 2 × 5
#                  date `unit31:depr1` `unit31:depr2` `unit36:depr2` `unit37:depr1`
#                <dttm>          <int>          <int>          <int>          <int>
# 1 2017-05-22 10:47:00              3              2              5              4
# 2 2017-05-22 11:04:00              6              3              5              4

最新更新