Python数据帧与groupby

Python数据帧与groupby,python,dataframe,group-by,median,Python,Dataframe,Group By,Median,我有一个包含三列的数据框,即,日期,商品和值。我想在df中添加另一列,median_20,即过去20天内每种商品的滚动中位数。此外,我还想添加其他列,这些列显示前几天的值,n,例如,lag\u 1列显示给定商品的前一天值,lag\u 2显示前两天值,等等。我的df很大(>200万行) 我相信有一种更有效的方法,同时尝试以下解决方案: for commo in df.market.unique(): df.loc[df.market==commo,'lag_1'] = df.loc[df.

我有一个包含三列的数据框,即,
日期
商品
。我想在
df
中添加另一列,
median_20
,即过去20天内每种
商品的滚动中位数。此外,我还想添加其他列,这些列显示前几天的值,
n
,例如,
lag\u 1
列显示给定
商品的前一天值,
lag\u 2
显示前两天值,等等。我的
df
很大(>200万行)


我相信有一种更有效的方法,同时尝试以下解决方案:

for commo in df.market.unique():
    df.loc[df.market==commo,'lag_1'] = df.loc[df.market==commo,'commodity'].shift(1)
    df.loc[df.market==commo,'median_20'] = pd.rolling_median(df.loc[df.market==commo,'commodity'],20)
尝试:

编辑: 以下内容应适用于版本
0.16.2

import numpy as np
import pandas as pd


np.random.seed(123)
dates = pd.date_range('2017-01-01', '2017-07-02')
df1 = pd.DataFrame({'date':dates, 'commodity':np.random.normal(size = len(dates)), 'market':'GOLD'})
df2 = pd.DataFrame({'date':dates, 'commodity':np.random.normal(size = len(dates)), 'market':'SILVER'})
df = pd.concat([df1, df2])
df = df.sort('date').reset_index(drop=True)

# create columns
df['median_20_temp'] = df.groupby('market')['commodity'].apply(lambda s: pd.rolling_median(s, 20))
df['median_20'] = df.groupby('market')['median_20_temp'].shift(1)
df['lag_1'] = df.groupby('market')['commodity'].shift(1)
df['lag_2'] = df.groupby('market')['commodity'].shift(2)
df.drop(['median_20_temp'], axis=1, inplace=True)

我希望这能有所帮助。

谢谢您的回复@Abdou。我尝试了这个方法,但它抛出了
AttributeError:'SeriesGroupBy'对象没有属性“rolling”
。在我的办公室,我们使用pandas的“0.16.2”版本,不幸的是,在我们的生产环境中升级它并不容易。这是执行第一条语句时出现的错误-
df['media_20']=…
第二条和第三条语句抛出以下错误-
pandas/core/groupby.py,第581行,在wrapper raise ValueError
@Gerry中不幸的是,我无法调试代码,因为我看不到数据。我正在处理你在这里提供的数据。请共享引发这些错误的数据。另外,请确保您使用的是最新版本的pandas。我在上面的数据框中发现了这些错误。正如你正确指出的,这些与我正在使用的熊猫版本有关。不幸的是,我不容易在我们的办公生产环境中升级pandas。
lag_1
lag_2
语句工作正常。然而,对于
median_20
语句,它并没有给出正确的结果。它没有失败,但如果您检查结果,这些不是
商品
列中前20个值的中间值。谢谢@user7235865。for循环中的第一条语句工作正常。但是,第二条语句-
df.loc[df.market==commo,'media_20']=…
抛出了
AttributeError:'Series'对象没有属性“rolling”
。我认为此错误可能与旧版本的pandas有关,但在我的办公室中,我们使用pandas的“0.16.2”版本,不幸的是,在我们的生产环境中升级它并不容易。有什么办法可以解决这个问题吗?@Gerry:用
pd尝试一下这个新版本。这就是我最后使用的,而且很有效。谢谢对于大数据帧,For循环速度非常慢。此外,
df.loc[df.market==commo,'media_20']…
语句直到最后才是中位数,但也包括当前行。解决此问题的一种方法是将shift(1)
应用于
中值20
列。
import pandas as pd
import numpy as np

# create dataframe
dates = pd.date_range('2017-01-01', '2017-07-02')
df1 = pd.DataFrame({'date':dates, 'commodity':np.random.normal(size = len(dates)), 'market':'GOLD'})
df2 = pd.DataFrame({'date':dates, 'commodity':np.random.normal(size = len(dates)), 'market':'SILVER'})
df = pd.concat([df1, df2])
df = df.sort_values(by='date').reset_index(drop=True)

# create columns
df['median_20_temp'] = df.groupby('market')['commodity'].rolling(20).median()
df['median_20'] = df.groupby('market')['median_20_temp'].shift(1)
df['lag_1'] = df.groupby('market')['commodity'].shift(1)
df['lag_2'] = df.groupby('market')['commodity'].shift(2)
df.drop(['median_20_temp'], axis=1, inplace=True)
import numpy as np
import pandas as pd


np.random.seed(123)
dates = pd.date_range('2017-01-01', '2017-07-02')
df1 = pd.DataFrame({'date':dates, 'commodity':np.random.normal(size = len(dates)), 'market':'GOLD'})
df2 = pd.DataFrame({'date':dates, 'commodity':np.random.normal(size = len(dates)), 'market':'SILVER'})
df = pd.concat([df1, df2])
df = df.sort('date').reset_index(drop=True)

# create columns
df['median_20_temp'] = df.groupby('market')['commodity'].apply(lambda s: pd.rolling_median(s, 20))
df['median_20'] = df.groupby('market')['median_20_temp'].shift(1)
df['lag_1'] = df.groupby('market')['commodity'].shift(1)
df['lag_2'] = df.groupby('market')['commodity'].shift(2)
df.drop(['median_20_temp'], axis=1, inplace=True)