如何用 r data.table 填写数据框中所有可能的列?
How to fill out all possible columns in a dataframe with r data.table?
假设我们从下面的 data
数据帧开始,由下面的代码生成:
> data
ID Period_1 Period_2 Values State
1 1 1 2020-01 5 X0
2 1 2 2020-02 10 X1
3 1 3 2020-03 15 X0
4 2 1 2020-04 0 X0
5 2 2 2020-05 2 X2
6 2 3 2020-06 4 X0
7 3 1 2020-02 3 X2
8 3 2 2020-03 6 X1
9 3 3 2020-04 9 X0
data <-
data.frame(
ID = c(1,1,1,2,2,2,3,3,3),
Period_1 = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
Period_2 = c("2020-01","2020-02","2020-03","2020-04","2020-05","2020-06","2020-02","2020-03","2020-04"),
Values = c(5, 10, 15, 0, 2, 4, 3, 6, 9),
State = c("X0","X1","X0","X0","X2","X0", "X2","X1","X0")
)
我正在尝试学习如何使用 R 包 data.table,并想用它来计算从给定状态(下面代码示例中的状态“X0”)到另一个状态的转换,当从一个周期移动或“过渡”到下一个周期时(在这种情况下,周期测量是“Period_1”)。当 运行 下面的 data.table 代码时,我得到以下结果:
OutflowState 2 4
1: X0 0 0
2: X1 1 0
3: X2 1 0
Code run:
library(data.table)
dcast(
setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID]
[, period_factor := lapply(.SD, factor), .SDcols = "Period_1"]
[, period_factor := as.numeric(period_factor) + 1],
OutflowState ~ period_factor, length,
value.var = "Values", subset = .(State == "X0"), drop = FALSE
)
此输出是正确的,但我想 (a) 向周期 1 和周期 3 的输出添加列(周期 1 将始终全为 0,周期 3 应在这种情况下显示全 0 data
dataframe 因为周期 2 中没有 state = X0;和 (b) 从输出中删除 Period_1 = 4 的列,因为没有周期 = 4,这只是代码中使用的一个技巧以上 as.numeric(period_factor) + 1
以标记下一个过渡期。我该怎么做?
当 运行 下面显示的代码段时,我得到以下临时数据帧,所以一种解决方案是删除 OutflowState = NA 的任何行(消除所有名义周期 4),但我不这样做知道怎么做了。
ID Period_1 Period_2 Values State OutflowState period_factor
1: 1 1 2020-01 5 X0 X1 2
2: 1 2 2020-02 10 X1 X0 3
3: 1 3 2020-03 15 X0 <NA> 4
4: 2 1 2020-04 0 X0 X2 2
5: 2 2 2020-05 2 X2 X0 3
6: 2 3 2020-06 4 X0 <NA> 4
7: 3 1 2020-02 3 X2 X1 2
8: 3 2 2020-03 6 X1 X0 3
9: 3 3 2020-04 9 X0 <NA> 4
setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID][
, period_factor := lapply(.SD, factor), .SDcols = "Period_1"][
, period_factor := as.numeric(period_factor) + 1
]
data
这个问题是 解决转型流入问题的产物。请注意,上面的 data.table 代码允许将时间范围定义为 Period_2 的替代方案,并且可以对值的转换求和而不是对转换进行计数,并且需要维护这些功能。
下图更能说明问题:
dcast
和 drop = FALSE
将为 period_factor
的每个因子水平创建列,因此您需要列 1
和 3
而不是 4
在结果中,我们需要将 period_factor
的级别设置为包括 1
和 3
但不包括 4
(并保持 factor
class!)。我也简化了 period_factor
的创建,仅当我们将其应用于多个列时才需要 lapply
和 .SDcols
:
dcast(
setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID]
[, period_factor := factor(Period_1 + 1, levels = seq(1, max(Period_1)))],
OutflowState ~ period_factor, length,
value.var = "Values",
subset = .(State == "X0" ),
drop = FALSE
)
# OutflowState 1 2 3
# 1: X0 0 0 0
# 2: X1 0 1 0
# 3: X2 0 1 0
我们可以从 to the question 中获取 state_inflow()
函数并将其转换为 state_outflow()
函数:
state_inflow <- function(mydat, target_state) {
dcast(
setDT(mydat)[, Previous_State := shift(State, fill = target_state), by = ID],
factor(Previous_State) ~ factor(Period_1), length, value.var = "Values",
subset = .(State == target_state), drop = FALSE
)
}
通过互换 State
和 Previous_State
在 dcast()
中的角色 :
state_outflow <- function(mydat, target_state) {
dcast(
setDT(mydat)[, Previous_State := shift(State), by = ID],
factor(State) ~ factor(Period_1), length, value.var = "Values",
subset = .(Previous_State == target_state), drop = FALSE
)
}
此外,shift()
函数没有提供任何填充值。所以,每个ID
第一期的前一个状态是NA
.
调用函数给出预期结果:
state_outflow(data, "X0")
State 1 2 3
1: X0 0 0 0
2: X1 0 1 0
3: X2 0 1 0
无需调整因子水平。
假设我们从下面的 data
数据帧开始,由下面的代码生成:
> data
ID Period_1 Period_2 Values State
1 1 1 2020-01 5 X0
2 1 2 2020-02 10 X1
3 1 3 2020-03 15 X0
4 2 1 2020-04 0 X0
5 2 2 2020-05 2 X2
6 2 3 2020-06 4 X0
7 3 1 2020-02 3 X2
8 3 2 2020-03 6 X1
9 3 3 2020-04 9 X0
data <-
data.frame(
ID = c(1,1,1,2,2,2,3,3,3),
Period_1 = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
Period_2 = c("2020-01","2020-02","2020-03","2020-04","2020-05","2020-06","2020-02","2020-03","2020-04"),
Values = c(5, 10, 15, 0, 2, 4, 3, 6, 9),
State = c("X0","X1","X0","X0","X2","X0", "X2","X1","X0")
)
我正在尝试学习如何使用 R 包 data.table,并想用它来计算从给定状态(下面代码示例中的状态“X0”)到另一个状态的转换,当从一个周期移动或“过渡”到下一个周期时(在这种情况下,周期测量是“Period_1”)。当 运行 下面的 data.table 代码时,我得到以下结果:
OutflowState 2 4
1: X0 0 0
2: X1 1 0
3: X2 1 0
Code run:
library(data.table)
dcast(
setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID]
[, period_factor := lapply(.SD, factor), .SDcols = "Period_1"]
[, period_factor := as.numeric(period_factor) + 1],
OutflowState ~ period_factor, length,
value.var = "Values", subset = .(State == "X0"), drop = FALSE
)
此输出是正确的,但我想 (a) 向周期 1 和周期 3 的输出添加列(周期 1 将始终全为 0,周期 3 应在这种情况下显示全 0 data
dataframe 因为周期 2 中没有 state = X0;和 (b) 从输出中删除 Period_1 = 4 的列,因为没有周期 = 4,这只是代码中使用的一个技巧以上 as.numeric(period_factor) + 1
以标记下一个过渡期。我该怎么做?
当 运行 下面显示的代码段时,我得到以下临时数据帧,所以一种解决方案是删除 OutflowState = NA 的任何行(消除所有名义周期 4),但我不这样做知道怎么做了。
ID Period_1 Period_2 Values State OutflowState period_factor
1: 1 1 2020-01 5 X0 X1 2
2: 1 2 2020-02 10 X1 X0 3
3: 1 3 2020-03 15 X0 <NA> 4
4: 2 1 2020-04 0 X0 X2 2
5: 2 2 2020-05 2 X2 X0 3
6: 2 3 2020-06 4 X0 <NA> 4
7: 3 1 2020-02 3 X2 X1 2
8: 3 2 2020-03 6 X1 X0 3
9: 3 3 2020-04 9 X0 <NA> 4
setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID][
, period_factor := lapply(.SD, factor), .SDcols = "Period_1"][
, period_factor := as.numeric(period_factor) + 1
]
data
这个问题是
下图更能说明问题:
dcast
和 drop = FALSE
将为 period_factor
的每个因子水平创建列,因此您需要列 1
和 3
而不是 4
在结果中,我们需要将 period_factor
的级别设置为包括 1
和 3
但不包括 4
(并保持 factor
class!)。我也简化了 period_factor
的创建,仅当我们将其应用于多个列时才需要 lapply
和 .SDcols
:
dcast(
setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID]
[, period_factor := factor(Period_1 + 1, levels = seq(1, max(Period_1)))],
OutflowState ~ period_factor, length,
value.var = "Values",
subset = .(State == "X0" ),
drop = FALSE
)
# OutflowState 1 2 3
# 1: X0 0 0 0
# 2: X1 0 1 0
# 3: X2 0 1 0
我们可以从 state_inflow()
函数并将其转换为 state_outflow()
函数:
state_inflow <- function(mydat, target_state) {
dcast(
setDT(mydat)[, Previous_State := shift(State, fill = target_state), by = ID],
factor(Previous_State) ~ factor(Period_1), length, value.var = "Values",
subset = .(State == target_state), drop = FALSE
)
}
通过互换 State
和 Previous_State
在 dcast()
中的角色 :
state_outflow <- function(mydat, target_state) {
dcast(
setDT(mydat)[, Previous_State := shift(State), by = ID],
factor(State) ~ factor(Period_1), length, value.var = "Values",
subset = .(Previous_State == target_state), drop = FALSE
)
}
此外,shift()
函数没有提供任何填充值。所以,每个ID
第一期的前一个状态是NA
.
调用函数给出预期结果:
state_outflow(data, "X0")
State 1 2 3 1: X0 0 0 0 2: X1 0 1 0 3: X2 0 1 0
无需调整因子水平。