获取特定类别的上一个日期的新列(Python)
我试图建立一个特定的预测模型。我决定用它来处理整个数据 这次用python代替DAX(pbi)来学习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/
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,不幸的是,我没有注意到我以相反的方式对数据帧进行排序。但是,我只想指出,您接受的方法是不安全的。它在将日期字符串转换为日期对象之前对数据帧进行排序,这可能会导致错误的结果。