我在IPython中有以下数据框,其中每一行都是一个股票:
In [261]: bdata
Out[261]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 21210 entries, 0 to 21209
Data columns:
BloombergTicker 21206 non-null values
Company 21210 non-null values
Country 21210 non-null values
MarketCap 21210 non-null values
PriceReturn 21210 non-null values
SEDOL 21210 non-null values
yearmonth 21210 non-null values
dtypes: float64(2), int64(1), object(4)
我想应用groupby操作,根据“yearmonth”列中的每个日期计算所有内容的上限加权平均回报 .
这按预期工作:
In [262]: bdata.groupby("yearmonth").apply(lambda x: (x["PriceReturn"]*x["MarketCap"]/x["MarketCap"].sum()).sum())
Out[262]:
yearmonth
201204 -0.109444
201205 -0.290546
但后来我希望将这些值“广播”回原始数据框中的索引,并将它们保存为日期匹配的常量列 .
In [263]: dateGrps = bdata.groupby("yearmonth")
In [264]: dateGrps["MarketReturn"] = dateGrps.apply(lambda x: (x["PriceReturn"]*x["MarketCap"]/x["MarketCap"].sum()).sum())
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/mnt/bos-devrnd04/usr6/home/espears/ws/Research/Projects/python-util/src/util/<ipython-input-264-4a68c8782426> in <module>()
----> 1 dateGrps["MarketReturn"] = dateGrps.apply(lambda x: (x["PriceReturn"]*x["MarketCap"]/x["MarketCap"].sum()).sum())
TypeError: 'DataFrameGroupBy' object does not support item assignment
我意识到这种天真的任务不应该奏效 . 但是,用于将groupby操作的结果分配到父数据帧的新列中的“正确”Pandas习惯是什么?
最后,我想要一个名为“MarketReturn”的列,而不是所有与groupby操作的输出具有匹配日期的索引的重复常量值 .
实现这一目标的一个方法是:
marketRetsByDate = dateGrps.apply(lambda x: (x["PriceReturn"]*x["MarketCap"]/x["MarketCap"].sum()).sum())
bdata["MarketReturn"] = np.repeat(np.NaN, len(bdata))
for elem in marketRetsByDate.index.values:
bdata["MarketReturn"][bdata["yearmonth"]==elem] = marketRetsByDate.ix[elem]
但这很慢,很糟糕,而且是非战斗的 .
5 回答
这有用吗?
我使用
reindex_like
:虽然我仍然在探索
apply
连接各个部分的所有非常智能的方式,但是在另一种方法是在groupby操作之后在父级中添加新列 .我可以建议
transform
方法(而不是聚合)吗?如果你在原始例子中使用它,它应该做你想要的(广播) .作为使用groupby()的一般规则,如果使用.transform()函数,pandas将返回一个与原始表格长度相同的表 . 当您使用其他函数(如.sum()或.first())时,pandas将返回一个表,其中每一行都是一个组 .
我不确定这如何适用于apply但是使用转换实现精心设计的lambda函数可能相当棘手,因此我认为最有用的策略是创建我需要的变量,将它们放在原始数据集中然后在那里进行操作 .
如果我理解你正在尝试做什么(我道歉,如果我弄错了),首先你可以计算每组的总市值:
这将在您的原始数据中添加一个名为“group_MarketCap”的列,其中包含每个组的市值总和 . 然后你可以直接计算加权值:
最后,您将使用相同的转换函数计算每个组的加权平均值:
我倾向于以这种方式构建我的变量 . 有时你可以把它全部放在一个命令中,但这并不总是适用于groupby(),因为大多数时候pandas需要实例化新对象以在完整的数据集范围内对它进行操作(即你不能如果还不存在,则将两列相加 .
希望这可以帮助 :)