pandas dataframe resample 聚合函数使用具有自定义函数的多列?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47938372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
pandas dataframe resample aggregate function use multiple columns with a customized function?
提问by StayFoolish
Here is an example:
下面是一个例子:
# Generate some random time series dataframe with 'price' and 'volume'
x = pd.date_range('2017-01-01', periods=100, freq='1min')
df_x = pd.DataFrame({'price': np.random.randint(50, 100, size=x.shape), 'vol': np.random.randint(1000, 2000, size=x.shape)}, index=x)
df_x.head(10)
price vol
2017-01-01 00:00:00 56 1544
2017-01-01 00:01:00 70 1680
2017-01-01 00:02:00 92 1853
2017-01-01 00:03:00 94 1039
2017-01-01 00:04:00 81 1180
2017-01-01 00:05:00 70 1443
2017-01-01 00:06:00 56 1621
2017-01-01 00:07:00 68 1093
2017-01-01 00:08:00 59 1684
2017-01-01 00:09:00 86 1591
# Here is some example aggregate function:
df_x.resample('5Min').agg({'price': 'mean', 'vol': 'sum'}).head()
price vol
2017-01-01 00:00:00 78.6 7296
2017-01-01 00:05:00 67.8 7432
2017-01-01 00:10:00 76.0 9017
2017-01-01 00:15:00 74.0 6989
2017-01-01 00:20:00 64.4 8078
However, if I want to extract other aggregated info depends on more than one column, what can I do?
但是,如果我想提取依赖于多个列的其他聚合信息,我该怎么办?
For example, I want to append 2 more columns here, called all_up
and all_down
.
例如,我想在此处再添加 2 列,称为all_up
和all_down
。
These 2 columns' calculations are defined as follows:
这 2 列的计算定义如下:
In every 5 minutes, how many times the 1-minute sampled price went down and vol went down, call this column all_down
, and how many times they are went up, call this column all_up
.
每 5 分钟,1 分钟采样价格下降多少次,成交量下降all_down
多少次,称为此列,上升多少次,称为此列all_up
。
Here is what I expect the 2 columns look like:
这是我期望的 2 列:
price vol all_up all_down
2017-01-01 00:00:00 78.6 7296 2 0
2017-01-01 00:05:00 67.8 7432 0 0
2017-01-01 00:10:00 76.0 9017 1 0
2017-01-01 00:15:00 74.0 6989 1 1
2017-01-01 00:20:00 64.4 8078 0 2
This functionality depends on 2 columns. But in the agg
function in the Resampler
object, it seems that it only accept 3 kinds of functions:
此功能取决于 2 列。但是在对象中的agg
函数中Resampler
,好像只接受3种函数:
- a
str
or a function that applies to each of the columns separately. - a
list
of functions that applies to each of the columns separately. - a
dict
with keys matches the column names. Still only apply the value which is a function to a single column each time.
- a
str
或分别应用于每一列的函数。 - 分别
list
应用于每一列的函数。 - a
dict
with keys 匹配列名。每次仍然只将作为函数的值应用于单个列。
All these functionalities seem doesn't meet my needs.
所有这些功能似乎都不能满足我的需求。
回答by jezrael
I think you need instead resample
use groupby
+ Grouper
and apply
with custom function:
我认为您需要resample
使用groupby
+Grouper
和apply
自定义函数:
def func(x):
#code
a = x['price'].mean()
#custom function working with 2 columns
b = (x['price'] / x['vol']).mean()
return pd.Series([a,b], index=['col1','col2'])
df_x.groupby(pd.Grouper(freq='5Min')).apply(func)
Or use resample
for all supported aggreagate functions and join outputs together with outputs of custom function:
或resample
用于所有支持的聚合函数并将输出与自定义函数的输出连接在一起:
def func(x):
#custom function
b = (x['price'] / x['vol']).mean()
return b
df1 = df_x.groupby(pd.Grouper(freq='5Min')).apply(func)
df2 = df_x.resample('5Min').agg({'price': 'mean', 'vol': 'sum'}).head()
df = pd.concat([df1, df2], axis=1)
EDIT: For check decreasing and increasing is used function diff
and compare with 0
, join both condition with &
and count by sum
:
编辑:为了检查减少和增加使用函数diff
并与 比较0
,将条件与&
和计数连接起来sum
:
def func(x):
v = x['vol'].diff().fillna(0)
p = x['price'].diff().fillna(0)
m1 = (v > 0) & (p > 0)
m2 = (v < 0) & (p < 0)
return pd.Series([m1.sum(), m2.sum()], index=['all_up','all_down'])
df1 = df_x.groupby(pd.Grouper(freq='5min')).apply(func)
print (df1)
all_up all_down
2017-01-01 00:00:00 2 0
2017-01-01 00:05:00 0 0
df2 = df_x.resample('5Min').agg({'price': 'mean', 'vol': 'sum'}).head()
df = pd.concat([df2, df1], axis=1)
print (df)
vol price all_up all_down
2017-01-01 00:00:00 7296 78.6 2 0
2017-01-01 00:05:00 7432 67.8 0 0