假设我有一个数据帧,如下所示:
In [1]: test_dup_df
Out[1]:
exe_price exe_vol flag
2008-03-13 14:41:07 84.5 200 yes
2008-03-13 14:41:37 85.0 10000 yes
2008-03-13 14:41:38 84.5 69700 yes
2008-03-13 14:41:39 84.5 1200 yes
2008-03-13 14:42:00 84.5 1000 yes
2008-03-13 14:42:08 84.5 300 yes
2008-03-13 14:42:10 84.5 88100 yes
2008-03-13 14:42:10 84.5 11900 yes
2008-03-13 14:42:15 84.5 5000 yes
2008-03-13 14:42:16 84.5 3200 yes
我想在时间14:42:10
分组一个重复的数据,并应用不同的函数到exe_price
和exe_vol
(例如,求和exe_vol
和计算卷加权平均值exe_price
)...我知道我能做到
In [2]: grouped = test_dup_df.groupby(level=0)
将重复索引分组,然后使用first()
或last()
函数获取第一行或最后一行,但这并不是我真正想要的。
是否有方法对不同列中的值进行分组,然后应用不同的(由我编写的)函数?
不太熟悉熊猫,但在纯numpy中,您可以:
tot_vol = np.sum(grouped['exe_vol'])
avg_price = np.average(grouped['exe_price'], weights=grouped['exe_vol'])
我喜欢@waitingkuo的答案,因为它非常清晰易读。
不管怎样,我一直保留着这个,因为它看起来确实更快——至少在熊猫版本0.10.0中是这样。这种情况可能(希望)在未来发生变化,因此一定要重新运行基准测试,特别是如果您使用的是不同版本的Pandas。
import pandas as pd
import io
import timeit
data = '''\
date time exe_price exe_vol flag
2008-03-13 14:41:07 84.5 200 yes
2008-03-13 14:41:37 85.0 10000 yes
2008-03-13 14:41:38 84.5 69700 yes
2008-03-13 14:41:39 84.5 1200 yes
2008-03-13 14:42:00 84.5 1000 yes
2008-03-13 14:42:08 84.5 300 yes
2008-03-13 14:42:10 10 88100 yes
2008-03-13 14:42:10 100 11900 yes
2008-03-13 14:42:15 84.5 5000 yes
2008-03-13 14:42:16 84.5 3200 yes'''
df = pd.read_table(io.BytesIO(data), sep='\s+', parse_dates=[[0, 1]],
index_col=0)
def func(subf):
exe_vol = subf['exe_vol'].sum()
exe_price = ((subf['exe_price']*subf['exe_vol']).sum()
/ exe_vol)
flag = True
return pd.Series([exe_price, exe_vol, flag],
index=['exe_price', 'exe_vol', 'flag'])
# return exe_price
def using_apply():
return df.groupby(df.index).apply(func)
def using_helper_column():
df['weight'] = df['exe_price'] * df['exe_vol']
grouped = df.groupby(level=0, group_keys=True)
result = grouped.agg({'weight': 'sum', 'exe_vol': 'sum'})
result['exe_price'] = result['weight'] / result['exe_vol']
result['flag'] = True
result = result.drop(['weight'], axis=1)
return result
result = using_apply()
print(result)
result = using_helper_column()
print(result)
time_apply = timeit.timeit('m.using_apply()',
'import __main__ as m ',
number=1000)
time_helper = timeit.timeit('m.using_helper_column()',
'import __main__ as m ',
number=1000)
print('using_apply: {t}'.format(t = time_apply))
print('using_helper_column: {t}'.format(t = time_helper))
产量
exe_vol exe_price flag
date_time
2008-03-13 14:41:07 200 84.50 True
2008-03-13 14:41:37 10000 85.00 True
2008-03-13 14:41:38 69700 84.50 True
2008-03-13 14:41:39 1200 84.50 True
2008-03-13 14:42:00 1000 84.50 True
2008-03-13 14:42:08 300 84.50 True
2008-03-13 14:42:10 100000 20.71 True
2008-03-13 14:42:15 5000 84.50 True
2008-03-13 14:42:16 3200 84.50 True
具有时间基准:
using_apply: 3.0081038475
using_helper_column: 1.35300707817
应用您自己的功能:
In [12]: def func(x):
exe_price = (x['exe_price']*x['exe_vol']).sum() / x['exe_vol'].sum()
exe_vol = x['exe_vol'].sum()
flag = True
return Series([exe_price, exe_vol, flag], index=['exe_price', 'exe_vol', 'flag'])
In [13]: test_dup_df.groupby(test_dup_df.index).apply(func)
Out[13]:
exe_price exe_vol flag
date_time
2008-03-13 14:41:07 84.5 200 True
2008-03-13 14:41:37 85 10000 True
2008-03-13 14:41:38 84.5 69700 True
2008-03-13 14:41:39 84.5 1200 True
2008-03-13 14:42:00 84.5 1000 True
2008-03-13 14:42:08 84.5 300 True
2008-03-13 14:42:10 20.71 100000 True
2008-03-13 14:42:15 84.5 5000 True
2008-03-13 14:42:16 84.5 3200 True
编辑:最后一个问题,如何通过值而不是引用来存储它?
我想知道如何为不同对象的数组指定JSON模式。这个线程给了我一半的答案,但当我有每种类型的对象的多个实例时,它就失败了。 下面是一个基于这里给出的示例的示例XML,但是重复了“product”对象:- 下面的模式将只在每种类型都有单个实例时(例如,如果“product”只出现一次)验证上面的XML。 为了增加娱乐性,我不能使用像“anyof”这样的关键字,因为我要将这个模式嵌入到一个Swagger
问题内容: 我正在练习继承。 我有两个相似的类,我想将其同化为一个数组,因此我想将Object类用作超类,因为所有内容都是Object的子类。 因此,例如,我将T类和CT类放入一个名为all的数组中,如下所示: 我跳过了声明,因为那不是我的问题。 当我希望使用循环在数组内调用函数时,我真正的问题就变成了: T和CT分别涉及的类都具有beingShot方法,该方法是公共的。 Eclipse建议将它们
打印c时,c的值是初始化的值,x,y都是1。a变化了不影响c。 那么函数d在初始化时,x:b(),y:a为什么不初始化为x:1,y:1呢,就是这样
问题内容: 我尝试过一些关于绑定和未绑定方法的代码。当我们调用它们时,我认为它们都会返回对象。但是,当我用于获取一些信息时,它返回的内容我并不理解。 IDE:Eclipse 插件:pydev 输出是… 为什么#1和#2返回相同的ID?他们不是不同的对象吗?如果我们分配和两个变量,#3,#4回报不同的ID。 我认为#3和#4表明它们不是同一对象,而是#1和#2 … 绑定方法的ID和未绑定方法的ID有
我是新来的Clojure和玩它的乐趣。 我正在阅读一个CSV文件,并希望对每一列应用一个不同的函数。什么是一个优雅的(既简洁又可读)方法来做到这一点?我探讨了两种方法: null 对于每一行... ...我想对每个元素应用一个不同的函数,得到这样的结果: 我要使用的函数是: null 使用此方法,我首先将每一行转换为一个映射: 编辑:并且我想获取此地图: 转换器也存储在映射中: 最后我会把数据放入