我有一个如下所示的数据集:
ID= c("A","A","A","A","B","B","C","C","C")
Date= as.Date(c("2017-09-24", "2017-09-26", "2017-09-23", "2017-09-30","2017-09-12", "2017-09-15", "2017-09-01", "2017-09-30", "2017-09-25"))
Data= c(10,5,15,20,8,9,5,6,2)
df= data.frame(ID, Date, Data)
d
ID Date Data
1 A 2017-09-24 10
2 A 2017-09-26 5
3 A 2017-09-23 15
4 A 2017-09-30 20
5 B 2017-09-12 8
6 B 2017-09-15 9
7 C 2017-09-01 5
8 C 2017-09-30 6
9 C 2017-09-25 2
我正在尝试按降序顺序添加按每个ID的Date列降序排列的其他列,以便我有以下输出:
ID Order Date Data
1 A 3 2017-09-24 10
2 A 2 2017-09-26 5
3 A 4 2017-09-23 15
4 A 1 2017-09-30 20
5 B 2 2017-09-12 8
6 B 1 2017-09-15 9
7 C 3 2017-09-01 5
8 C 1 2017-09-30 6
9 C 2 2017-09-25 2
我已经使用了striptime()和order()来尝试获取Order列,但我不确定如何根据ID循环它。
然后我尝试旋转数据框,以便每个Order都有自己的列,并且观察结果是数据列中包含的数据:
ID Order4 Order3 Order2 Order1
1 A 15 10 5 20
2 B 8 9
3 C 5 2 6
我曾尝试使用tidyr的spread()来完成数据集的旋转,但由于存在不同长度的列,因此效果不佳。
非常感谢
答案 0 :(得分:0)
关于你的第一个问题。
library(dplyr)
df2 <- df %>%
group_by(ID) %>%
mutate(Order = dense_rank(desc(Date))) %>%
ungroup() %>%
select(ID, Order, Date, Data)
# df2
# ID Order Date Data
# <fct> <int> <date> <dbl>
# 1 A 3 2017-09-24 10.0
# 2 A 2 2017-09-26 5.00
# 3 A 4 2017-09-23 15.0
# 4 A 1 2017-09-30 20.0
# 5 B 2 2017-09-12 8.00
# 6 B 1 2017-09-15 9.00
# 7 C 3 2017-09-01 5.00
# 8 C 1 2017-09-30 6.00
# 9 C 2 2017-09-25 2.00
关于你的第二个问题。
library(tidyr)
df3 <- df2 %>%
select(-Date) %>%
mutate(Order = paste0("Order", Order)) %>%
spread(Order, Data)
df3
# # A tibble: 3 x 5
# ID Order1 Order2 Order3 Order4
# * <fct> <dbl> <dbl> <dbl> <dbl>
# 1 A 20.0 5.00 10.0 15.0
# 2 B 9.00 8.00 NA NA
# 3 C 6.00 2.00 5.00 NA
答案 1 :(得分:0)
使用库data.table
library(data.table)
df= data.frame(ID, Date, Data)
setDT(df)[,Order:=(.N:1)[rank(Date)],by=ID][,.(ID,Order,Date,Data)]
ID Order Date Data
1: A 3 2017-09-24 10
2: A 2 2017-09-26 5
3: A 4 2017-09-23 15
4: A 1 2017-09-30 20
5: B 2 2017-09-12 8
6: B 1 2017-09-15 9
7: C 3 2017-09-01 5
8: C 1 2017-09-30 6
9: C 2 2017-09-25 2
dcast(df[,order:=.(paste0("Order",Order))],ID~order,value.var = "Data")
ID Order1 Order2 Order3 Order4
1: A 20 5 10 15
2: B 9 8 NA NA
3: C 6 2 5 NA
答案 2 :(得分:0)
OP要求将数据集从长格式转换为宽格式,其中每个ID
的订单应按Date
的降序编号,即最近的订单将显示在列中Order1
,Order2
中的第二个最近订单等,
这可以通过dcast()
一步使用rowid()
功能实现:
library(data.table)
dcast(setDT(df)[order(-Date)], ID ~ rowid(ID, prefix = "Order"))
ID Order1 Order2 Order3 Order4 1: A 20 5 10 15 2: B 9 8 NA NA 3: C 6 2 5 NA
现在,OP的预期结果也显示Order
列也按降序排列。这可以通过扭转因子水平来实现:
dcast(setDT(df)[order(-Date)], ID ~ forcats::fct_rev(rowid(ID, prefix = "Order")))
ID Order4 Order3 Order2 Order1 1: A 15 10 5 20 2: B NA NA 8 9 3: C NA 5 2 6
最后,我们可以通过胁迫角色来摆脱NA
值:
dcast(setDT(df)[order(-Date)], ID ~ forcats::fct_rev(rowid(ID, prefix = "Order")),
toString)
ID Order4 Order3 Order2 Order1 1: A 15 10 5 20 2: B 8 9 3: C 5 2 6
现在,这几乎完全复制了OP的预期结果。
如果每ID
个订单超过9个,则需要修改列名以保持列的正确顺序:
dcast(setDT(df)[order(-Date)], ID ~ forcats::fct_rev(sprintf("Order%02i", rowid(ID))),
toString)
%02i
调用中的格式说明符sprintf()
可确保订单号在转换为字符时始终使用两位数。比较sort(as.character(1:10))
与sort(sprintf("%02i", 1:10))
。