Bir zaman serisi veri çerçevesi için satırlar nasıl eklenir?
Bir zaman serisi excel dosyasını bir veri çerçevesine yükleyecek bir program yazıyorum, ardından bazı temel hesaplamaları kullanarak birkaç yeni sütun oluşturuyorum. Programım bazen bazı kayıtlar için aylar eksik olan excel dosyalarını okuyacak. Aşağıdaki örnekte iki farklı mağaza için aylık satış verilerim var. Mağazalar farklı aylarda açılır, bu nedenle ilk ay sonları farklı olacaktır. Ancak her ikisinin de 30/9/2020 tarihine kadar ay sonu verileri olması gerekir. Dosyamda, Mağaza BBB'nin 8/31/2020 ve 9/30/2020 için kayıtları yok çünkü o aylarda Satış yoktu.
Mağaza | Açılan Ay | Durum | Kent | Ay Bitiş Tarihi | Satış |
---|---|---|---|---|---|
AAA | 31.05.2020 | NY | New York | 31.05.2020 | 1000 |
AAA | 31.05.2020 | NY | New York | 30.06.2020 | 5000 |
AAA | 31.05.2020 | NY | New York | 30.07.2020 | 3000 |
AAA | 31.05.2020 | NY | New York | 31.08.2020 | 4000 |
AAA | 31.05.2020 | NY | New York | 30.09.2020 | 2000 |
BBB | 30.06.2020 | CT | Hartford | 30.06.2020 | 100 |
BBB | 30.06.2020 | CT | Hartford | 30.07.2020 | 200 |
Dolayısıyla, bunun gibi herhangi bir durum için, 8/31 ve 9/30 için Mağaza BBB için iki satır ekleyebilmek istiyorum. Yeni satırlar, en son ay sonu tarihinden itibaren aynı Açılış Ayı, Eyalet ve Şehri kullanmalıdır. Satış, her iki yeni satır için 0 olarak ayarlanmalıdır. Şu andan itibaren aşağıdaki adımları uyguluyorum:
- Mağaza adı ve her Mağaza için maksimum Ay Bitiş Tarihi ve ayrıca tüm zaman serisi veri çerçevesi için maksimum Ay Bitiş Tarihi ile Veri Çerçevesi "MaxDateData" oluşturun, bu alanı "En Yakın Tarih" olarak adlandırıyorum.
Mağaza | Maksimum Ay Bitiş Tarihi | En Son Tarih |
---|---|---|
AAA | 30.09.2020 | 30.09.2020 |
BBB | 30.07.2020 | 30.09.2020 |
- Ana zaman serisi veri çerçevesinden en son satırı içeren "MostRecent" Dataframe'ini oluşturun. Bunu yapmak için, zaman serisi veri çerçevesi ile Mağaza Adı ve Maks Ay Bitiş Tarihindeki MaxDateData arasında bir iç birleştirme yapıyorum.
Mağaza | Açılan Ay | Durum | Kent | Ay Bitiş Tarihi | Satış | Maksimum Ay Bitiş Tarihi | En Son Tarih |
---|---|---|---|---|---|---|---|
AAA | 31.05.2020 | NY | New York | 30.09.2020 | 2000 | 30.09.2020 | 30.09.2020 |
BBB | 30.06.2020 | CT | Hartford | 30.07.2020 | 200 | 30.07.2020 | 30.09.2020 |
- Max Ay Bitiş Tarihi <En Son Tarih olan mağazaları filtrelemek için bir where cümlesi kullanarak bir "RequireBackfill_MostRecent" veri çerçevesi oluşturun. Aşağıdaki koda bakın. Dolayısıyla bu örnekte, RequireBackfill_MostRecent tablosunda yalnızca BBB deposu için bir satır olacaktır.
RequireBackfill_Stores_MostRecent = MaxDateData.where(MaxDateData['Max Month End Date'] <MaxDateData['Most Recent Date'])
RequireBackfill_MostRecent = MostRecent.merge(RequireBackfill_Stores_MostRecent,how='inner')
- Daha sonra doldurmam gereken tarihler arasında geçiş yapmak için iki yuvalanmış for döngüsü kullanıyorum. Yalnızca Mağaza BBB'yi içeren RequireBackfill_MostRecent veri çerçevesinden yararlanıyor.
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)
- Daha sonra, concat kullanarak zaman serisi veri çerçeveme NewData ekledim
FullData_List = [MonthlyData,NewData]
FullData=pd.concat(FullData_List)
Tüm bu süreç işe yarıyor ama bunu yapmanın çok daha verimli bir yolu var mı? Daha büyük verilerle çalışmaya başladığımda bu maliyetli hale gelebilir.
Yanıtlar
- sadece
upsample
DateTime indeksini deneyin . ref: pandalar-yeniden örnekleme-örnek-son-tarih-kenar-veri
# group by `Store`
# with `Month End Date` column show be converted to DateTime
group.set_index(['Month End Date']).resample('M').asfreq()
- dikkat edin:
7/30/2020
Temmuz ayının sonu değil.7/31/2020
dır-dir. Bu nedenle, bu yöntemi kullanmak7/30/2020
bir sorun olacaktır (Ay Bitiş Tarihini gerçekten bitiş tarihi olarak dönüştürün).
İşte bunu yapmak için adım adım yaklaşım. Sorularınız varsa bana bildirin.
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)
Bunun çıktısı:
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
Not Size daha fazla varyasyon göstermek için CCC ile bir giriş daha ekledim.