timeseries 데이터 프레임에 행을 추가하는 방법은 무엇입니까?
Dec 31 2020
timeseries 엑셀 파일에서 데이터 프레임에로드되는 프로그램을 작성하고 있으며 몇 가지 기본 계산을 사용하여 여러 개의 새 열을 만듭니다. 내 프로그램은 때때로 일부 레코드에 대해 몇 달이 누락 된 Excel 파일을 읽을 것입니다. 따라서 아래 예에는 두 개의 다른 상점에 대한 월별 판매 데이터가 있습니다. 상점은 다른 달에 열리므로 첫 번째 월말 날짜가 다릅니다. 그러나 둘 다 2020 년 9 월 30 일까지 월말 데이터를 가져야합니다. 내 파일에서 Store BBB에는 2020 년 8 월 31 일 및 2020 년 9 월 30 일에 대한 기록이 없습니다.
저장 | 개설 된 달 | 상태 | 시티 | 월 종료일 | 매상 |
---|---|---|---|---|---|
AAA | 2020 년 5 월 31 일 | NY | 뉴욕 | 2020 년 5 월 31 일 | 1000 |
AAA | 2020 년 5 월 31 일 | NY | 뉴욕 | 2020 년 6 월 30 일 | 5000 |
AAA | 2020 년 5 월 31 일 | NY | 뉴욕 | 2020 년 7 월 30 일 | 3000 |
AAA | 2020 년 5 월 31 일 | NY | 뉴욕 | 2020 년 8 월 31 일 | 4000 |
AAA | 2020 년 5 월 31 일 | NY | 뉴욕 | 2020 년 9 월 30 일 | 2000 년 |
BBB | 2020 년 6 월 30 일 | CT | Hartford | 2020 년 6 월 30 일 | 100 |
BBB | 2020 년 6 월 30 일 | CT | Hartford | 2020 년 7 월 30 일 | 200 |
따라서 이와 같은 인스턴스의 경우 8/31 및 9/30에 대해 Store BBB에 대해 두 행을 추가 할 수 있기를 원합니다. 새 행은 가장 최근의 월말 날짜와 동일한 개설 된 월, 주 및시를 사용해야합니다. 새 행 모두에 대해 Sales를 0으로 설정해야합니다. 지금은 다음 단계를 수행합니다.
- 상점 이름과 각 상점에 대한 최대 월 종료 날짜 및 전체 시계열 데이터 프레임에 대한 최대 월 종료 날짜를 사용하여 데이터 프레임 "MaxDateData"를 작성하고이 필드의 이름을 "가장 최근 날짜"로 지정합니다.
저장 | 최대 월 종료 날짜 | 가장 최근 날짜 |
---|---|---|
AAA | 2020 년 9 월 30 일 | 2020 년 9 월 30 일 |
BBB | 2020 년 7 월 30 일 | 2020 년 9 월 30 일 |
- 기본 시계열 데이터 프레임의 가장 최근 행으로 "MostRecent"데이터 프레임을 만듭니다. 이를 위해 시계열 데이터 프레임과 Store Name 및 Max Month End Date의 MaxDateData 사이에 내부 조인을 수행합니다.
저장 | 개설 된 달 | 상태 | 시티 | 월 종료일 | 매상 | 최대 월 종료 날짜 | 가장 최근 날짜 |
---|---|---|---|---|---|---|---|
AAA | 2020 년 5 월 31 일 | NY | 뉴욕 | 2020 년 9 월 30 일 | 2000 년 | 2020 년 9 월 30 일 | 2020 년 9 월 30 일 |
BBB | 2020 년 6 월 30 일 | CT | Hartford | 2020 년 7 월 30 일 | 200 | 2020 년 7 월 30 일 | 2020 년 9 월 30 일 |
- Where 절을 사용하여 "RequireBackfill_MostRecent"데이터 프레임을 만들어 최대 월 종료 날짜 <가장 최근 날짜 인 상점을 필터링합니다. 아래 코드를 참조하십시오. 따라서이 예에서 RequireBackfill_MostRecent 테이블에는 상점 BBB에 대한 행만 있습니다.
RequireBackfill_Stores_MostRecent = MaxDateData.where(MaxDateData['Max Month End Date'] <MaxDateData['Most Recent Date'])
RequireBackfill_MostRecent = MostRecent.merge(RequireBackfill_Stores_MostRecent,how='inner')
- 그런 다음 두 개의 중첩 된 for 루프를 사용하여 채워야하는 날짜를 순환합니다. Store BBB 만 포함하는 RequireBackfill_MostRecent 데이터 프레임을 활용합니다.
X=[]
end = MaxDateData['Most Recent Date'][0]
for i in MonthlyData['Month End Date'].unique():
per1 = pd.date_range(start = i, end = end, freq ='M')
for val in per1:
Data=[]
Data = RequireBackfill_MostRecent[["Store"
,"Month Opened"
,"City"
,"State"
]].where(RequireBackfill_MostRecent['Max Month End date']==i).dropna()
Data["Month End Date"]= val
Data["Sales"]= 0
X.append(Data)
NewData = pd.concat(X)
- 그런 다음 concat을 사용하여 NewData를 내 timeseries 데이터 프레임에 추가합니다.
FullData_List = [MonthlyData,NewData]
FullData=pd.concat(FullData_List)
이 전체 프로세스가 작동하지만이를 수행하는 훨씬 더 효율적인 방법이 있습니까? 더 큰 데이터로 작업을 시작하면 비용이 많이들 수 있습니다.
답변
Ferris Dec 31 2020 at 14:08
upsample
DateTime 인덱스를 사용해보십시오 . 참조 : pandas-resample-upsample-last-date-edge-of-data
# group by `Store`
# with `Month End Date` column show be converted to DateTime
group.set_index(['Month End Date']).resample('M').asfreq()
- 주의 할 점 :
7/30/2020
7 월 말이 아닙니다.7/31/2020
이다. 따라서이 방법7/30/2020
을 사용 하는 것은 문제가 될 것입니다 (월 종료일을 진정한 종료일로 변환).
JoeFerndz Dec 31 2020 at 16:14
이를위한 단계별 접근 방식은 다음과 같습니다. 질문이 있으면 알려주세요.
import pandas as pd
pd.set_option('display.max_columns', None)
c = ['Store','Month Opened','State','City','Month End Date','Sales']
d = [['AAA','5/31/2020','NY','New York','5/31/2020',1000],
['AAA','5/31/2020','NY','New York','6/30/2020',5000],
['AAA','5/31/2020','NY','New York','7/30/2020',3000],
['AAA','5/31/2020','NY','New York','8/31/2020',4000],
['AAA','5/31/2020','NY','New York','9/30/2020',2000],
['BBB','6/30/2020','CT','Hartford','6/30/2020',100],
['BBB','6/30/2020','CT','Hartford','7/30/2020',200],
['CCC','3/31/2020','NJ','Cranbury','3/31/2020',1500]]
df = pd.DataFrame(d,columns = c)
df['Month Opened'] = pd.to_datetime(df['Month Opened'])
df['Month End Date'] = pd.to_datetime(df['Month End Date'])
#select last entry for each Store
df1 = df.sort_values('Month End Date').drop_duplicates('Store', keep='last').copy()
#delete all rows that have 2020-09-30. We want only ones that are less than 2020-09-30
df1 = df1[df1['Month End Date'] != '2020-09-30']
#set target end date to 2020-09-30
df1['Target_End_Date'] = pd.to_datetime ('2020-09-30')
#calculate how many rows to repeat
df1['repeats'] = df1['Target_End_Date'].dt.to_period('M').astype(int) - df1['Month End Date'].dt.to_period('M').astype(int)
#add 1 month to month end so we can start repeating from here
df1['Month End Date'] = df1['Month End Date'] + pd.DateOffset(months =1)
#set sales value as 0 per requirement
df1['Sales'] = 0
#repeat each row by the value in column repeats
df1 = df1.loc[df1.index.repeat(df1.repeats)].reset_index(drop=True)
#reset repeats to start from 0 thru n using groupby cumcouunt
#this will be used to calculate months to increment from month end date
df1['repeats'] = df1.groupby('Store').cumcount()
#update month end date based on value in repeats
df1['Month End Date'] = df1.apply(lambda x: x['Month End Date'] + pd.DateOffset(months = x['repeats']), axis=1)
#set end date to last day of the month
df1['Month End Date'] = pd.to_datetime(df1['Month End Date']) + pd.offsets.MonthEnd(0)
#drop columns that we don't need anymore. required before we concat dfs
df1.drop(columns=['Target_End_Date','repeats'],inplace=True)
#concat df and df1 to get the final dataframe
df = pd.concat([df, df1], ignore_index=True)
#sort values by Store and Month End Date
df = df.sort_values(by=['Store','Month End Date'],ignore_index=True)
print (df)
결과는 다음과 같습니다.
Store Month Opened State City Month End Date Sales
0 AAA 2020-05-31 NY New York 2020-05-31 1000
1 AAA 2020-05-31 NY New York 2020-06-30 5000
2 AAA 2020-05-31 NY New York 2020-07-30 3000
3 AAA 2020-05-31 NY New York 2020-08-31 4000
4 AAA 2020-05-31 NY New York 2020-09-30 2000
5 BBB 2020-06-30 CT Hartford 2020-06-30 100
6 BBB 2020-06-30 CT Hartford 2020-07-30 200
7 BBB 2020-06-30 CT Hartford 2020-08-30 0
8 BBB 2020-06-30 CT Hartford 2020-09-30 0
9 CCC 2020-03-31 NJ Cranbury 2020-03-31 1500
10 CCC 2020-03-31 NJ Cranbury 2020-04-30 0
11 CCC 2020-03-31 NJ Cranbury 2020-05-31 0
12 CCC 2020-03-31 NJ Cranbury 2020-06-30 0
13 CCC 2020-03-31 NJ Cranbury 2020-07-31 0
14 CCC 2020-03-31 NJ Cranbury 2020-08-31 0
15 CCC 2020-03-31 NJ Cranbury 2020-09-30 0
참고 더 많은 변형을 보여주기 위해 CCC와 함께 항목을 하나 더 추가했습니다.