我已经搜索了网络以寻求解决方案,但是,无法找到该特定主题的答案。
我有一个数据框,显示了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