Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
获取特定类别的上一个日期的新列(Python)_Python_Pandas_Data Science_Data Manipulation - Fatal编程技术网

获取特定类别的上一个日期的新列(Python)

获取特定类别的上一个日期的新列(Python),python,pandas,data-science,data-manipulation,Python,Pandas,Data Science,Data Manipulation,我试图建立一个特定的预测模型。我决定用它来处理整个数据 这次用python代替DAX(pbi)来学习python 我有两列与这个问题相关:客户和日期。 每一行都是在特定日期为该客户创建的发票 我正在尝试为每一行(发票)获取上一个发票日期。理解是很重要的 新列必须考虑客户,这意味着对于每个客户的发票,我希望获得发票的上一个日期 这就是它的样子: data = [['A', 17/07/2020], ['B', 15/07/2020], ['C', 14/07/2020], ['C', 10/07/

我试图建立一个特定的预测模型。我决定用它来处理整个数据 这次用python代替DAX(pbi)来学习python

我有两列与这个问题相关:客户和日期。 每一行都是在特定日期为该客户创建的发票

我正在尝试为每一行(发票)获取上一个发票日期。理解是很重要的 新列必须考虑客户,这意味着对于每个客户的发票,我希望获得发票的上一个日期

这就是它的样子:

data = [['A', 17/07/2020], ['B', 15/07/2020], ['C', 14/07/2020], ['C', 10/07/2020], ['B', 09/07/2020]]
df = pd.DataFrame(data, columns = ['Customer', 'Date'])
print(df)

Customer Date
A        17/07/2020
B        15/07/2020
C        14/07/2020
C        10/07/2020
B        09/07/2020  
这就是我寻求的结果:

Customer Date        PrevInvoiceDate
A        17/07/2020  NaT
B        15/07/2020  09/07/2020
C        14/07/2020  10/07/2020
C        10/07/2020  NaT
B        09/07/2020  NaT
我试着使用熊猫的移位、定位、过滤器等。。但是没有运气, 我会很感激学习正确的方法来做这种操纵,并向你们大家学习。
谢谢。

首先,您的
Date
列的类型是string而不是datetime。让我们把它转换成datetime。然后,按日期对数据框进行排序

df['Date'] = pd.to_datetime(df['Date'])
df = df.sort_values('Date')

# Output:
Customer    Date
0   A   17/07/2020
1   B   15/07/2020
2   C   14/07/2020
3   C   10/07/2020
4   B   09/07/2020
然后,按
Customer
对数据帧进行分组,然后使用
apply()
函数。对于每个组(特定客户的所有发票),将
日期
列移动1

df['PrevInvoiceDate'] = df.groupby('Customer')['Date'].shift(periods=1)

# Output:
Customer    Date    PrevInvoiceDate
2   C   2020-07-14  NaT
1   B   2020-07-15  NaT
0   A   2020-07-17  NaT
4   B   2020-09-07  2020-07-15
3   C   2020-10-07  2020-07-14
另外,函数
shift()
默认情况下会将列值向下移动1,因此可以去掉
periods=1
。在这里,我只是想让你明白它的作用

最后,如果您想恢复原始日期格式,我们可以将日期时间转换回字符串

df['Date'] = df['Date'].dt.strftime('%d/%m/%Y')
df['PrevInvoiceDate'] = df['PrevInvoiceDate'].dt.strftime('%d/%m/%Y')

df.sort_index()  # (Optional) Sort the dataframe by its original index

# Output:
    Customer    Date    PrevInvoiceDate
0   A   17/07/2020  NaN
1   B   15/07/2020  NaN
2   C   14/07/2020  NaN
3   C   07/10/2020  14/07/2020
4   B   07/09/2020  15/07/2020

首先,看起来您的
Date
列的类型是string而不是datetime。让我们把它转换成datetime。然后,按日期对数据框进行排序

df['Date'] = pd.to_datetime(df['Date'])
df = df.sort_values('Date')

# Output:
Customer    Date
0   A   17/07/2020
1   B   15/07/2020
2   C   14/07/2020
3   C   10/07/2020
4   B   09/07/2020
然后,按
Customer
对数据帧进行分组,然后使用
apply()
函数。对于每个组(特定客户的所有发票),将
日期
列移动1

df['PrevInvoiceDate'] = df.groupby('Customer')['Date'].shift(periods=1)

# Output:
Customer    Date    PrevInvoiceDate
2   C   2020-07-14  NaT
1   B   2020-07-15  NaT
0   A   2020-07-17  NaT
4   B   2020-09-07  2020-07-15
3   C   2020-10-07  2020-07-14
另外,函数
shift()
默认情况下会将列值向下移动1,因此可以去掉
periods=1
。在这里,我只是想让你明白它的作用

最后,如果您想恢复原始日期格式,我们可以将日期时间转换回字符串

df['Date'] = df['Date'].dt.strftime('%d/%m/%Y')
df['PrevInvoiceDate'] = df['PrevInvoiceDate'].dt.strftime('%d/%m/%Y')

df.sort_index()  # (Optional) Sort the dataframe by its original index

# Output:
    Customer    Date    PrevInvoiceDate
0   A   17/07/2020  NaN
1   B   15/07/2020  NaN
2   C   14/07/2020  NaN
3   C   07/10/2020  14/07/2020
4   B   07/09/2020  15/07/2020
试试这个:

import pandas as pd
data = [['A', '17/07/2020'], ['B', '15/07/2020'], ['C', '14/07/2020'], ['C', '10/07/2020'], ['B', '09/07/2020']]
df = pd.DataFrame(data, columns = ['Customer', 'Date'])
df=df.sort_values(by=['Customer','Date'])
df['test']=df.groupby('Customer')['Date'].shift()
print(df)
  Customer        Date        test
0        A  17/07/2020         NaN
4        B  09/07/2020         NaN
1        B  15/07/2020  09/07/2020
3        C  10/07/2020         NaN
2        C  14/07/2020  10/07/2020
试试这个:

import pandas as pd
data = [['A', '17/07/2020'], ['B', '15/07/2020'], ['C', '14/07/2020'], ['C', '10/07/2020'], ['B', '09/07/2020']]
df = pd.DataFrame(data, columns = ['Customer', 'Date'])
df=df.sort_values(by=['Customer','Date'])
df['test']=df.groupby('Customer')['Date'].shift()
print(df)
  Customer        Date        test
0        A  17/07/2020         NaN
4        B  09/07/2020         NaN
1        B  15/07/2020  09/07/2020
3        C  10/07/2020         NaN
2        C  14/07/2020  10/07/2020

这是卷的。一种方法是
left merge df
,使用
groupby
结果,使用apply选择每组中最后一个上一个。选择重复的索引并将其设为空

     import numpy as np
df2=df.merge(df.groupby('Customer')['Date'].apply(lambda x: x.iloc[1:]).\
             reset_index().rename(columns={'Date':'PrevInvoiceDate'}),\
             how='left',on='Customer').drop(columns=['level_1'])

df2.loc[df2.loc[df2["PrevInvoiceDate"].duplicated('first')].\
        index,'PrevInvoiceDate']=np.nan



     Customer        Date      PrevInvoiceDate
0        A       17/07/2020             NaN
1        B       15/07/2020      09/07/2020
2        C       14/07/2020      10/07/2020
3        C       10/07/2020             NaN
4        B       09/07/2020             NaN

这是卷的。一种方法是
left merge df
,使用
groupby
结果,使用apply选择每组中最后一个上一个。选择重复的索引并将其设为空

     import numpy as np
df2=df.merge(df.groupby('Customer')['Date'].apply(lambda x: x.iloc[1:]).\
             reset_index().rename(columns={'Date':'PrevInvoiceDate'}),\
             how='left',on='Customer').drop(columns=['level_1'])

df2.loc[df2.loc[df2["PrevInvoiceDate"].duplicated('first')].\
        index,'PrevInvoiceDate']=np.nan



     Customer        Date      PrevInvoiceDate
0        A       17/07/2020             NaN
1        B       15/07/2020      09/07/2020
2        C       14/07/2020      10/07/2020
3        C       10/07/2020             NaN
4        B       09/07/2020             NaN

这是可行的,但有一种更简单的方法。不过,我会将此应用于其他情况,谢谢。这是可行的,但有一种更简单的方法。不过,我会将此应用于其他情况,谢谢。这与我需要的正好相反,但这对于我需要得到与我这次需要相反的结果的情况非常有用。谢谢。@DanielMillionshik,不幸的是,我没有注意到我以相反的方式对数据帧进行排序。但是,我只想指出,您接受的方法是不安全的。它在将日期字符串转换为日期对象之前对数据帧进行了排序,这可能会给您错误的结果。这与我所需要的正好相反,但这对于我这次需要得到相反结果的情况非常有用。谢谢。@DanielMillionshik,不幸的是,我没有注意到我以相反的方式对数据帧进行排序。但是,我只想指出,您接受的方法是不安全的。它在将日期字符串转换为日期对象之前对数据帧进行排序,这可能会导致错误的结果。