使用条件语句将 df 从长格式重塑为宽格式

问题描述 投票:0回答:1

我有一个

long df
,看起来像这样:

df <- data.frame(id=as.integer(c(123,123,123,124,124,124,125,125,126,126,126)),
                 date=as.Date(c("2014-03-12", "2015-05-02", "2015-09-16", "2015-10-24", "2016-12-11", "2017-10-17", "2017-08-06", "2018-01-29", "2015-09-16", "2015-11-12", "2015-12-03")),
                 event=as.character(c("A", "C", "E", "A", "B", "D", "A", "E", "A", "B", "E")),
                 order=as.integer(c(1,2,3,1,2,3,1,2,1,2,3)),
                 diff=as.integer(c(0,416,553,0,414,724,0,176,0,57,78)))

df
    id       date event order diff
1  123 2014-03-12     A     1    0
2  123 2015-05-02     C     2  416
3  123 2015-09-16     E     3  553
4  124 2015-10-24     A     1    0
5  124 2016-12-11     B     2  414
6  124 2017-10-17     D     3  724
7  125 2017-08-06     A     1    0
8  125 2018-01-29     E     2  176
9  126 2015-09-16     A     1    0
10 126 2015-11-12     B     2   57
11 126 2015-12-03     E     3   78

每个

id
始终有一个初始事件
A
和最终事件,要么
D
要么
E
(互斥)。事件
B
C
可能发生也可能不发生。
diff
是每个事件的
days
与每个
date
的初始事件
date
A
之间的
id
之差。

我想获得一个

wide df
,其中每个事件都是
column
(例如
A_status
),其中
0= absent
1= present
。同样,每个通讯员
diff
都是一个
column
(例如
A_time
)。但是,当事件
B
C
不存在时(例如
B= 0
C= 0
),我希望他们的
time
D_time
E_time
填充,以存在的为准。

我需要根据

columns
values
D
创建两个
E

  1. a
    column
    D.E_status
    ,其中
    0=D
    1=E
    ,以及
  2. a
    column
    D.E_time
    将接收记录的
    time
    D
    E
    )。

这是所需的输出:

id  A_status A_time B_status B_time C_status C_time D.E_status  D.E_time
123 1        0      0        553    1        416    1           553
124 1        0      1        414    0        724    0           724
125 1        0      0        176    0        176    1           176
126 1        0      1        78     0        78     1           78

鉴于我非常基本的 R 技能,我非常感谢您在这方面的帮助。

r conditional-statements reshape wide-format-data
1个回答
0
投票

我将演示一个

dplyr
/
tidyr
解决方案。首先,我认为
B_time
的最后一个值应该是
57
而不是
78

library(dplyr)
library(tidyr) # pivot_wider
df %>%
  mutate(
    status = if_else(event == "D", 0, 1),
    event = if_else(event %in% c("D", "E"), "D.E", event)
  ) %>%
  pivot_wider(
    id_cols = "id",
    names_from = "event", values_from = c("diff", "status")
  ) %>%
  rename_with(.fn = ~ sub("diff", "time", sub("(.*)_(.*)", "\\2_\\1", .))) %>%
  mutate(
    across(c(C_time, B_time), ~ coalesce(., D.E_time)),
    across(c(C_status, B_status), ~ +(!is.na(.)))
  )
# # A tibble: 4 × 9
#      id A_time C_time D.E_time B_time A_status C_status D.E_status B_status
#   <int>  <int>  <int>    <int>  <int>    <dbl>    <int>      <dbl>    <int>
# 1   123      0    416      553    553        1        1          1        0
# 2   124      0    724      724    414        1        0          0        1
# 3   125      0    176      176    176        1        0          1        0
# 4   126      0     78       78     57        1        0          1        1
© www.soinside.com 2019 - 2024. All rights reserved.