我在 Spotfire 中有一个数据集,其中每行包含 TASK_START 和 TASK_END 列,以及其他几个包含值的列。
作为示例输入,如下所示:
任务_开始 | 任务_END | 用户 | 项目 |
---|---|---|---|
24 年 1 月 1 日 | 24 年 3 月 1 日 | 姓名1 | 项目1 |
24 年 1 月 1 日 | 24 年 4 月 1 日 | 姓名1 | 项目2 |
24 年 2 月 1 日 | 24 年 4 月 1 日 | 名称2 | 项目3 |
我希望看到这样的输出:
月 | 用户 | 项目 |
---|---|---|
1月24日 | 姓名1 | 项目1 |
2 月 24 日 | 姓名1 | 项目1 |
1月24日 | 姓名1 | 项目2 |
2 月 24 日 | 姓名1 | 项目2 |
3 月 24 日 | 姓名1 | 项目2 |
2 月 24 日 | 名称2 | 项目3 |
3 月 24 日 | 名称2 | 项目3 |
我正在考虑使用 SQL 在数据源中执行此操作,但负责源数据的人员不愿意创建我想要的视图,因此我考虑使用 Spotfire 进行转换。我所有的研究都指向 R 和 Lubridate,但我还没有找到一个完全符合我想要的示例,而且由于我是 R 新手,所以还没有设法适应我找到的任何示例。
如果有人能指出我正确的方向,我将非常感激。
编辑:这是我在 Tibco 文档中查看的资源: https://support.tibco.com/s/article/How-to-create-a-continuous-date-range-given-start-and-end-dates-in-TIBCO-Spotfire-with-Data-Functions 但这似乎假设结束日期是下一个块的开始,而我的数据集有很多重叠的时间跨度。
欢迎来到SO!我不确定我是否完全遵循逻辑,但这将是我的尝试。哦,总是很高兴使用
dput()
向人们提供数据以实现可重复性:
# data
dat <- structure(
list(
TASK_START = c("01-JAN-24", "01-JAN-24", "01-FEB-24"),
TASK_END = c("01-MAR-24", "01-APR-24", "01-APR-24"),
USER = c("name1", "name1", "name2"),
PROJECT = c("project1", "project2", "project3")
),
row.names = c(NA, -3L), class = "data.frame"
)
我更喜欢使用
data.table
进行数据操作,但总有一个 dplyr
解决方案。首先我投射到data.table
。对于此解决方案,您需要 lubridate
和 data.table
。
library(lubridate)
library(data.table)
# cast to data.table
dat <- data.table::as.data.table(dat)
然后我转换成长格式并按用户和项目排序:
# cast long
dat <- data.table::melt(
dat,
id.vars = c("USER", "PROJECT"),
variable.name = "TYPE",
value.name = "MONTH"
)
# arrange by user, project
data.table::setorder(dat, USER, PROJECT)
> dat
USER PROJECT TYPE MONTH
<char> <char> <fctr> <char>
1: name1 project1 TASK_START 01-JAN-24
2: name1 project1 TASK_END 01-MAR-24
3: name1 project2 TASK_START 01-JAN-24
4: name1 project2 TASK_END 01-APR-24
5: name2 project3 TASK_START 01-FEB-24
6: name2 project3 TASK_END 01-APR-24
从那里,我用
lubridate
解析日期时间:
# parse time (dmy)
dat[, MONTH := lubridate::dmy(MONTH)]
这是我有点困惑的地方 - 在你想要的输出中,看起来你想要 TASK_END - 1 个月,所以这就是我在这里所做的。
# if task-end, then -1 month
dat[TYPE == "TASK_END", MONTH := MONTH - months(1)]
> dat
USER PROJECT TYPE MONTH
<char> <char> <fctr> <Date>
1: name1 project1 TASK_START 2024-01-01
2: name1 project1 TASK_END 2024-02-01
3: name1 project2 TASK_START 2024-01-01
4: name1 project2 TASK_END 2024-03-01
5: name2 project3 TASK_START 2024-02-01
6: name2 project3 TASK_END 2024-03-01
最后,我按用户和项目在最小月份和最大月份之间进行排序,如果任务需要超过 1 个月才能完成,则将填写月份:
# expand month if gap
dat <- dat[,
.(MONTH = seq(min(MONTH), max(MONTH), by = "1 month")),
by = .(USER, PROJECT)
]
> dat
USER PROJECT MONTH
<char> <char> <Date>
1: name1 project1 2024-01-01
2: name1 project1 2024-02-01
3: name1 project2 2024-01-01
4: name1 project2 2024-02-01
5: name1 project2 2024-03-01
6: name2 project3 2024-02-01
7: name2 project3 2024-03-01
最后,我将格式设置为我引用的月份年份本文不断进行日期格式化并将月份设置为第一列:
# format as month-year
dat[, MONTH := format(MONTH, "%b-%y")]
# set month as first column
data.table::setcolorder(dat, "MONTH")
我们剩下:
> dat
MONTH USER PROJECT
<char> <char> <char>
1: Jan-24 name1 project1
2: Feb-24 name1 project1
3: Jan-24 name1 project2
4: Feb-24 name1 project2
5: Mar-24 name1 project2
6: Feb-24 name2 project3
7: Mar-24 name2 project3