R 使用data.table将值从一列扩展到多个新列

R 使用data.table将值从一列扩展到多个新列,r,data.table,data-manipulation,R,Data.table,Data Manipulation,我有一张客户ID表,按年度显示付款情况。第一个(众多)客户如下所示: ID Payment Year 112 0 2004 112 0 2005 112 0 2006 112 9592 2007 112 12332 2008 112 9234 2011 112 5400 2012 112 7392 2014 112

我有一张客户ID表,按年度显示付款情况。第一个(众多)客户如下所示:

 ID    Payment    Year
112          0    2004
112          0    2005
112          0    2006
112       9592    2007
112      12332    2008
112       9234    2011
112       5400    2012
112       7392    2014
112       8321    2015
 ID    Payment    Year   T-1  T-2  T-3  T-4  T-5  T-6  T-7  T-8  T-9 T-10   
112          0    2004  NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
112          0    2005     0 NULL NULL NULL NULL NULL NULL NULL NULL NULL
112          0    2006     0    0 NULL NULL NULL NULL NULL NULL NULL NULL
112        952    2007     0    0    0 NULL NULL NULL NULL NULL NULL NULL
112       1232    2008   952    0    0    0 NULL NULL NULL NULL NULL NULL
112        924    2011  NULL NULL 1232  952    0    0    0 NULL NULL NULL 
112        500    2012   924 NULL NULL 1232  952    0    0    0 NULL NULL 
112        392    2014  NULL  500  924 NULL NULL 1232  952    0    0    0
112        821    2015   392 NULL  500  924 NULL NULL 1232  952    0    0
请注意,有些年份已经过去了。我需要为每行创建10个新列,显示过去10年的付款情况。生成的表应如下所示:

 ID    Payment    Year
112          0    2004
112          0    2005
112          0    2006
112       9592    2007
112      12332    2008
112       9234    2011
112       5400    2012
112       7392    2014
112       8321    2015
 ID    Payment    Year   T-1  T-2  T-3  T-4  T-5  T-6  T-7  T-8  T-9 T-10   
112          0    2004  NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
112          0    2005     0 NULL NULL NULL NULL NULL NULL NULL NULL NULL
112          0    2006     0    0 NULL NULL NULL NULL NULL NULL NULL NULL
112        952    2007     0    0    0 NULL NULL NULL NULL NULL NULL NULL
112       1232    2008   952    0    0    0 NULL NULL NULL NULL NULL NULL
112        924    2011  NULL NULL 1232  952    0    0    0 NULL NULL NULL 
112        500    2012   924 NULL NULL 1232  952    0    0    0 NULL NULL 
112        392    2014  NULL  500  924 NULL NULL 1232  952    0    0    0
112        821    2015   392 NULL  500  924 NULL NULL 1232  952    0    0
(我知道这是重复数据——它正在为预测模型做准备,在该模型中,以前的付款(和其他信息)将用于预测本年度的付款)

在SQL中,我将把表留给它自己,在ID和Year=(Year-1)上进行连接。。。但我不知道在R怎么做

我还考虑过使用dplyr按ID分组,然后在解组之前使用lag对新列进行变异。但是我的桌子很大,我想这太慢了。理想情况下,我希望改用data.table,但不知道如何使用


非常感谢您的帮助。

您首先将所有日期和ID进行合并,以获得缺少的年份:

dftot <- merge(df,CJ(Year =seq(min(df$Year),max(df$Year),1),ID = unique(df$ID)),all = T,by = "Year")
dftot[,ID := ID.y]
dftot[,c("ID.x","ID.y") := NULL]
dftot[,Year := as.numeric(Year)]
dftot <- dftot[order(Year)]

    Year Payment  ID
 1: 2004       0 112
 2: 2005       0 112
 3: 2006       0 112
 4: 2007    9592 112
 5: 2008   12332 112
 6: 2009      NA 112
 7: 2010      NA 112
 8: 2011    9234 112
 9: 2012    5400 112
10: 2013      NA 112
11: 2014    7392 112
12: 2015    8321 112
这应该是相当有效的,应该处理多个ID


数据

library(data.table)
df <- setDT(read.table(text = "ID    Payment    Year
112          0    2004
                       112          0    2005
                       112          0    2006
                       112       9592    2007
                       112      12332    2008
                       112       9234    2011
                       112       5400    2012
                       112       7392    2014
                       112       8321    2015",header = T))
库(data.table)

df首先合并所有日期和ID,以获得缺失的年份:

dftot <- merge(df,CJ(Year =seq(min(df$Year),max(df$Year),1),ID = unique(df$ID)),all = T,by = "Year")
dftot[,ID := ID.y]
dftot[,c("ID.x","ID.y") := NULL]
dftot[,Year := as.numeric(Year)]
dftot <- dftot[order(Year)]

    Year Payment  ID
 1: 2004       0 112
 2: 2005       0 112
 3: 2006       0 112
 4: 2007    9592 112
 5: 2008   12332 112
 6: 2009      NA 112
 7: 2010      NA 112
 8: 2011    9234 112
 9: 2012    5400 112
10: 2013      NA 112
11: 2014    7392 112
12: 2015    8321 112
这应该是相当有效的,应该处理多个ID


数据

library(data.table)
df <- setDT(read.table(text = "ID    Payment    Year
112          0    2004
                       112          0    2005
                       112          0    2006
                       112       9592    2007
                       112      12332    2008
                       112       9234    2011
                       112       5400    2012
                       112       7392    2014
                       112       8321    2015",header = T))
库(data.table)

df这里有一个基本的R选项,类似于@denis的解决方案

u <- merge(df1,
  data.frame(ID = unique(df1$ID), Year = min(df1$Year):max(df1$Year)),
  by = c("ID", "Year"), all = TRUE
)

subset(cbind(u, `colnames<-`(do.call(
  rbind,
  lapply(
    Reduce(c, c(NA, u$Payment), accumulate = TRUE)[1:nrow(u)],
    function(x) `length<-`(head(rev(x), 10), 10)
  )
), paste0("T-", 1:10))), !is.na(Payment))
数据

> dput(df1)
structure(list(ID = c(112L, 112L, 112L, 112L, 112L, 112L, 112L, 
112L, 112L), Payment = c(0L, 0L, 0L, 9592L, 12332L, 9234L, 5400L,
7392L, 8321L), Year = c(2004L, 2005L, 2006L, 2007L, 2008L, 2011L,
2012L, 2014L, 2015L)), class = "data.frame", row.names = c(NA,
-9L))

这是一个基本的R选项,类似于@denis的解决方案

u <- merge(df1,
  data.frame(ID = unique(df1$ID), Year = min(df1$Year):max(df1$Year)),
  by = c("ID", "Year"), all = TRUE
)

subset(cbind(u, `colnames<-`(do.call(
  rbind,
  lapply(
    Reduce(c, c(NA, u$Payment), accumulate = TRUE)[1:nrow(u)],
    function(x) `length<-`(head(rev(x), 10), 10)
  )
), paste0("T-", 1:10))), !is.na(Payment))
数据

> dput(df1)
structure(list(ID = c(112L, 112L, 112L, 112L, 112L, 112L, 112L, 
112L, 112L), Payment = c(0L, 0L, 0L, 9592L, 12332L, 9234L, 5400L,
7392L, 8321L), Year = c(2004L, 2005L, 2006L, 2007L, 2008L, 2011L,
2012L, 2014L, 2015L)), class = "data.frame", row.names = c(NA,
-9L))

请用dput(df)生成的structure()命令替换给定的数据帧,好吗!第一个:。然后:Henrik-我喜欢第二个链接中的答案,使用shift,但它不按ID分组-它总是从上面的行中获取,即使它们是不同的ID。我不确定第一个链接是如何关联的?请用dput(df)生成的structure()命令替换给定的数据帧好吗!第一个:。然后:Henrik-我喜欢第二个链接中的答案,使用shift,但它不按ID分组-它总是从上面的行中获取,即使它们是不同的ID。我不确定第一个链接是如何关联的?我认为这几乎可以实现,但当我有ID时,它似乎会中断,而我只有一年的付款。我得到以下错误:付款错误[1:(.N-I)]:只有0可能与负认购混合。当它到达任何有超过1行但少于10行的借款人时,它就会中断。如果我将行数改为5行,那么当它到达少于5行的借款人时,它将中断。你能编辑你的示例吗?我将以复制pbI的示例为例看一看,我认为这几乎有效,但当我有仅一年付款的ID时似乎会中断。我得到以下错误:付款错误[1:(.N-I)]:只有0可能与负认购混合。当它到达任何超过1但少于10的借款人时,它会中断,排。如果我将行数改为5行,那么当它到达少于5行的借款人时,它将中断。你能编辑你的示例吗?我将看一看复制pb的示例