【问题标题】:Python: Pivot tabel based on month in a datePython:基于日期中的月份的数据透视表
【发布时间】:2020-03-26 09:38:45
【问题描述】:

我想根据日期中的月份来旋转我的表格。

预期的示例结果:

    jul,revenue,aug,revenue,sept,revenue,okt,revenue,nov,revenue,dec,revenue,jan,revenue,feb,revenue,mar,revenue,apr,revenue,may,revenue,jun,revenue
Jul-2017,1000,Aug-2017,1000,Sep-2017,1000,Oct-2017,1000,Nov-2017,1000,Dec-2017,1000,Jan-2018,1000,Feb-2018,1000,Mar-2018,1000,Apr-2018,1000,May-2018,1000,Jun-2018,1000
Jul-2018,1000,Aug-2018,1000,Sep-2018,1000,Oct-2018,1000,Nov-2018,1000,Dec-2018,1000,Jan-2019,1000,Feb-2019,1000,Mar-2019,1000,Apr-2019,1000,May-2019,1000,Jun-2019,1000
Jul-2019,1000,Aug-2019,1000,Sep-2019,1000,Oct-2019,1000,Nov-2019,1000,Dec-2019,1000,Jan-2020,1000,Feb-2020,1000,Mar-2020,1000,Apr-2020,0,May-2020,0,Jun-2020,0

我用这段代码试了一下:

import pandas as pd
from datetime import date
df = pd.read_excel (r'examplefile')
ndf = df[['Saleprice', 'Date' , 'Season', 'Area', 'Place', 'Bookingsnumber']].reset_index(drop=True)
ndf['Date'] = pd.to_datetime(ndf['Date'])

#Revenue per Year/Month
ndf['my'] = ndf['Date'].map(lambda x: x.strftime('%m/%Y'))
grouped_ndf = ndf.groupby('my').sum().reset_index()
print(grouped_ndf)

控制台给了我这个结果:

            my  Saleprice
0  01/2019       2000
1  01/2020       3000
2  02/2019       4000
3  02/2020       6000

示例文件:

Saleprice,Date,Season,Area,Place,Bookingsnumber,Buy
1000,1-1-2019,winter 2019/2020,Zillertal,Mayrhofen,C20015243,800
1000,3-2-2019,winter 2019/2020,Zillertal,Königsleiten,B20015245,800
1000,5-2-2019,winter 2019/2020,Zell am See / Kaprun,Zell am See,C20015246,800
1000,1-1-2020,winter 2019/2020,Zell am See / Kaprun,Zell am See,D20015248,800
1000,3-2-2020,winter 2019/2020,Les Trois Vallées,Val Thorens,C20015249,800
1000,5-2-2020,winter 2019/2020,Zillertal,Königsleiten,C20015251,800
1000,1-1-2019,winter 2019/2020,Zillertal,Königsleiten,C20015252,800
1000,3-2-2019,winter 2019/2020,Espace Killy - Tignes,Tignes-Les-Brévières,C20015250,800
1000,5-2-2019,winter 2019/2020,Zillertal,Gerlos,B20015253,800
1000,1-1-2020,winter 2020/2021,Les Trois Vallées,Les Menuires,C20015254,800
1000,3-2-2020,winter 2020/2021,Zell am See / Kaprun,Zell am See,B20015255,800
1000,5-2-2020,winter 2020/2021,Zell am See / Kaprun,Zell am See,D20015256,800
1000,1-1-2020,winter 2020/2021,Les Trois Vallées,Les Menuires,E20015254,800
1000,3-2-2020,winter 2020/2021,Zell am See / Kaprun,Zell am See,B20015255,800
1000,5-2-2020,winter 2020/2021,Zell am See / Kaprun,Zell am See,B20015256,800

要获得示例结果,我必须进行哪些更改?期待你的回复。

【问题讨论】:

  • 我不知道 2017 年来自哪里,因为您的所有数据都来自 2019/2020 年
  • 你是对的。这是一个更大的例子 :) 使用示例文件,您只能获得 2019/2020 年的日期。本金是相同的(列 jan + year,saleprice,列 feb + year,saleprice)。你有解决办法吗?干杯

标签: python pandas datetime pivot pandas-groupby


【解决方案1】:

这段代码完成了这项工作,它不是最 Python 的,但这是我能想到的全部:

df['Date'] = df['Date'].apply(lambda x: pd.to_datetime(x))
months = df['Date'].apply(lambda x: x.strftime('%b')).unique()
df['my'] = df['Date'].map(lambda x: x.strftime('%b/%Y'))
dfgrouped = df.groupby('my')['Saleprice'].sum().reset_index()
month_dfs = [*map(lambda x: dfgrouped[dfgrouped['my'].str[:3]==x].reset_index(drop=True).rename(columns={'my': x, 'Saleprice': 'revenue'}), months)]
new_df = pd.concat(month_dfs, axis=1)

请注意,pd.to_datetime 将 Date 列中的第一个数字视为月份,如果您希望第二个数字为月份,则必须执行以下操作:

from datetime import datetime
df['Date'] = df['Date'].apply(lambda x: datetime.strptime(x, '%d-%m-%Y'))
months = df['Date'].apply(lambda x: x.strftime('%b')).unique()
df['my'] = df['Date'].map(lambda x: x.strftime('%b/%Y'))
dfgrouped = df.groupby('my')['Saleprice'].sum().reset_index()
month_dfs = [*map(lambda x: dfgrouped[dfgrouped['my'].str[:3]==x].reset_index(drop=True).rename(columns={'my': x, 'Saleprice': 'revenue'}), months)]
new_df = pd.concat(month_dfs, axis=1)

如果要对月份进行排序:

from datetime import datetime
df['Date'] = df['Date'].apply(lambda x: datetime.strptime(x, '%m-%d-%Y'))
months_in_df = months = df['Date'].apply(lambda x: x.strftime('%b')).unique()
months = []
for i in range(1,13):
    if datetime.date(2020, i, 1).strftime('%b') in months_in_df:
        months.append((i, datetime.date(2020, i, 1).strftime('%b')))

df['my'] = df['Date'].map(lambda x: x.strftime('%b/%Y'))
dfgrouped = df.groupby('my')['Saleprice'].sum().reset_index()
month_dfs = [*map(lambda x: dfgrouped[dfgrouped['my'].str[:3]==x].reset_index(drop=True).rename(columns={'my': x, 'Saleprice': 'revenue'}), months)]
new_df = pd.concat(month_dfs, axis=1)

【讨论】:

  • 谢谢您的回复!我使用你的第二个脚本。几个问题: - * map 的作用是什么 - 'str[:3]==x]' 有什么作用? - 当我用每个月的日期和print(new_df) 扩展我的示例文件时,控制台按以下顺序显示结果:5 月、2 月、1 月、9 月、12 月、6 月、7 月、8 月、10 月、11 月。如何按时间顺序从 jan 到 dec 排序?期待您的回答。杰伦
  • map 在元素列表中应用一个函数,在这种情况下,几个月,它只是避免 for 循环的另一种方法。 str[:3] 是月份的缩写,所以我基本上是从特定月份获取数据帧,而不用担心年份。我想您可以通过对月份列表进行排序来对其进行排序,我将添加另一个代码,以便您尝试看看是否有效。
  • 感谢您的快速回复@BrunoMello。您的新代码在第 2 行给了我一个错误:TypeError: strptime() argument 1 must be str, not Timestamp。怎么解决?干杯。
  • 我做到了。它给了我同样的错误。我把这段代码放在你最后一个脚本上面:import pandas as pd from datetime import date from datetime import datetime df = pd.read_excel (r'C:examplefile.xlsx')
  • 希望您有时间回答我的问题?我使用日期列中的第一个数字作为月份。您的最后一个代码没有。它使用第二个数字作为月份。我想当你重写第一个数字是月份的最后一个代码时,问题就解决了。你能为我做这个吗?
猜你喜欢
  • 1970-01-01
  • 2022-10-17
  • 2023-01-09
  • 2018-10-15
  • 1970-01-01
  • 1970-01-01
  • 2019-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多