我试图计算行数创建间隔的天数差异。
我的名为SELECT extract(xmlval,'/EMP/EMPNO/text()').getNumberVal() as empno
FROM Xml_tab WHERE
existsnode(xmlval,'/EMP/EMPNO') = 1 ;
的数据集如下所示,
temp
所以我的问题是如何通过ID计算日期之间的差异?所以ID 31933是2天,31750 6,20和1天。 我尝试了其他几个例子,例如
ID Event
31933 11/12/2016
31933 11/14/2016
31750 09/04/2016
31750 09/10/2016
31750 09/30/2016
31750 10/01/2016
30995 09/04/2016
30995 09/09/2016
30995 09/10/2016
30995 9/24/2016
此处的错误是library(zoo)
setDT(temp)
Interval<- function(x) difftime(x[3], x[1],units = "days")
temp[, INTERVAL := rollapply(Event, 3, diff, align = "left", fill = NA), by= ID]
。对于最快的情况,检查和强制会对性能产生太大影响。要么更改目标列的类型,要么强制{= 1} :(例如,使用1L而不是1)&#34;
还尝试了一些data.table函数,但它们没有用。
我对R很陌生,所以我想有一个简单的解决方案。
答案 0 :(得分:2)
data.table
和lubridate
:
library(lubridate)
library(data.table)
setDT(df)[, Days := c(NA, diff(mdy(Event))), by=ID]
或:
setDT(df)[, Days := mdy(Event)-lag(mdy(Event)), by=ID]
<强>结果:强>
ID Event Days
1: 31933 11/12/2016 NA days
2: 31933 11/14/2016 2 days
3: 31750 09/04/2016 NA days
4: 31750 09/10/2016 6 days
5: 31750 09/30/2016 20 days
6: 31750 10/01/2016 1 days
7: 30995 09/04/2016 NA days
8: 30995 09/09/2016 5 days
9: 30995 09/10/2016 1 days
10: 30995 9/24/2016 14 days
您还可以使用dplyr
和lubridate
library(lubridate)
library(dplyr)
df %>%
group_by(ID) %>%
mutate(Event = mdy(Event),
Days = Event - lag(Event))
<强>结果:强>
# A tibble: 10 x 3
# Groups: ID [3]
ID Event Days
<int> <date> <time>
1 31933 2016-11-12 NA days
2 31933 2016-11-14 2 days
3 31750 2016-09-04 NA days
4 31750 2016-09-10 6 days
5 31750 2016-09-30 20 days
6 31750 2016-10-01 1 days
7 30995 2016-09-04 NA days
8 30995 2016-09-09 5 days
9 30995 2016-09-10 1 days
10 30995 2016-09-24 14 days
或者如果您想删除NA行:
df %>%
group_by(ID) %>%
mutate(Event = mdy(Event),
Days = Event - lag(Event)) %>%
filter(Days > 0)
<强>结果:强>
# A tibble: 7 x 3
# Groups: ID [3]
ID Event Days
<int> <date> <time>
1 31933 2016-11-14 2 days
2 31750 2016-09-10 6 days
3 31750 2016-09-30 20 days
4 31750 2016-10-01 1 days
5 30995 2016-09-09 5 days
6 30995 2016-09-10 1 days
7 30995 2016-09-24 14 days
数据:强>
df = structure(list(ID = c(31933L, 31933L, 31750L, 31750L, 31750L,
31750L, 30995L, 30995L, 30995L, 30995L), Event = structure(c(6L,
7L, 1L, 3L, 4L, 5L, 1L, 2L, 3L, 8L), .Label = c("09/04/2016",
"09/09/2016", "09/10/2016", "09/30/2016", "10/01/2016", "11/12/2016",
"11/14/2016", "9/24/2016"), class = "factor")), .Names = c("ID",
"Event"), class = "data.frame", row.names = c(NA, -10L))
答案 1 :(得分:1)
有几个问题:
日期应该是"Date"
课程,而不是"character"
课程
,NA
是合乎逻辑的。写入NA
类型为NA_real_
通常没关系,但在这种情况下,由于data.table的工作方式,它很重要。
如果您将代码缩进4个空格,那么SO会为您格式化
问题中没有显示所需的输出,但是从代码中询问每隔一行之间的差异。我们显示了每个其他行的解决方案,但是如果您想要连续的行,则在每个解决方案中将2替换为1。
使用上面我们这样写:
library(data.table)
library(zoo)
setDT(temp)
temp$Event <- as.Date(temp$Event, "%m/%d/%Y")
roll <- function(x, k) rollapply(x, k+1, diff, lag = k, align = "left", fill = NA_real_)
temp[, INTERVAL := roll(as.numeric(Event), 2), by = ID]
给出所有其他行案例:
> temp
ID Event INTERVAL
1: 31933 2016-11-12 NA
2: 31933 2016-11-14 NA
3: 31750 2016-09-04 26
4: 31750 2016-09-10 21
5: 31750 2016-09-30 NA
6: 31750 2016-10-01 NA
7: 30995 2016-09-04 6
8: 30995 2016-09-09 15
9: 30995 2016-09-10 NA
10: 30995 2016-09-24 NA
这个使用data.table的shift
的替代方法也可以使用,只需要data.table:
temp[, INTERVAL := as.numeric(shift(Event, 2, type = "lead") - Event), by = ID]
如果您打算连续的行而不是每隔一行,则使用1替换上述任一解决方案中的2。
可重复形式的输入是:
Lines <- "ID Event
31933 11/12/2016
31933 11/14/2016
31750 09/04/2016
31750 09/10/2016
31750 09/30/2016
31750 10/01/2016
30995 09/04/2016
30995 09/09/2016
30995 09/10/2016
30995 09/24/2016"
temp <- read.table(text = Lines, header = TRUE)
答案 2 :(得分:0)
日期类以按天测量日期的格式存储,因此您可以使用它们执行简单的关节模拟,as per this SO thread.
它使用YYYY / MM / DD格式。例如
abs(as.Date("2016/11/12") - as.Date("2016/11/14"))
Time difference of 2 days
如果您将日期重新格式化为YYYY / MM / DD,您应该可以使用,例如,
abs(temp[1, 2] - temp[2, 2])
确定前两行中日期之间的差异。
答案 3 :(得分:0)
非常感谢你的所有建议。我想通了。
temp<- data.table(ID,Event, key = c("ID", "Event"))
temp[,INTER := c(0,'units<-'(diff(Event), "days")),by= ID]
然后将其与我的数据集合并。假设它不是很优雅,但它有效。