Python 在重采样的方式=中插入新的不存在列

Python 在重采样的方式=中插入新的不存在列,python,pandas,resampling,Python,Pandas,Resampling,我在看书 解决办法是: frame.resample('1H', how={'radiation': np.sum, 'tamb': np.mean}) 假设我想向存储其他函数值的结果中添加一个不存在的列,比如count()。在给出的示例中,假设我要计算每个1H周期中的行数 是否有可能做到: frame.resample('1H', how={'radiation': np.sum, 'tamb': np.mean,\ 'new_column': count()}

我在看书

解决办法是:

frame.resample('1H', how={'radiation': np.sum, 'tamb': np.mean})
假设我想向存储其他函数值的结果中添加一个不存在的列,比如count()。在给出的示例中,假设我要计算每个1H周期中的行数

是否有可能做到:

frame.resample('1H', how={'radiation': np.sum, 'tamb': np.mean,\
               'new_column': count()})
注意,新的_列不是原始数据框中的现有列

我问的原因是,我需要这样做,我有一个非常大的数据帧,我不想对原始df进行两次重采样,只是为了得到重采样期间的计数

我现在正在尝试上面的方法,似乎需要很长时间(没有语法错误)。不确定python是否陷入某种永久循环中

更新:

我执行了使用agg的建议(非常感谢)

但是,我在计算第一个聚合器时收到以下错误:

grouped = df.groupby(['name1',pd.TimeGrouper('M')])
    return pd.DataFrame(
    {'new_col1': grouped['col1'][grouped['col1'] > 0].agg('sum')
    ...


/Users/blahblah/anaconda/lib/python2.7/site-packages/pandas/core/groupby.pyc in __getitem__(self, key)
    521 
    522     def __getitem__(self, key):
--> 523         raise NotImplementedError('Not implemented: %s' % key)
    524 
    525     def _make_wrapper(self, name):

NotImplementedError: Not implemented: True
当我使用
grouped.apply(foo)
时,下面的方法很有效


重采样
类似于使用
时间分组器进行分组
。当重新采样时
how
参数仅允许您为每列指定一个聚合器,
df.GroupBy(…)
返回的
GroupBy
对象有一个
agg
方法,可以通过各种函数(例如
mean
sum
count
)以各种方式聚合组。您可以使用这些结果构建所需的数据帧:

import datetime as DT
import numpy as np
import pandas as pd
np.random.seed(2016)

date_times = pd.date_range(DT.datetime(2012, 4, 5, 8, 0),
                           DT.datetime(2012, 4, 5, 12, 0),
                           freq='1min')
tamb = np.random.sample(date_times.size) * 10.0
radiation = np.random.sample(date_times.size) * 10.0
df = pd.DataFrame(data={'tamb': tamb, 'radiation': radiation},
                  index=date_times)

resampled = df.resample('1H', how={'radiation': np.sum, 'tamb': np.mean})
print(resampled[['radiation', 'tamb']])
#                       radiation      tamb
# 2012-04-05 08:00:00  279.432788  4.549235
# 2012-04-05 09:00:00  310.032188  4.414302
# 2012-04-05 10:00:00  257.504226  5.056613
# 2012-04-05 11:00:00  299.594032  4.652067
# 2012-04-05 12:00:00    8.109946  7.795668

def using_agg(df):
    grouped = df.groupby(pd.TimeGrouper('1H'))
    return pd.DataFrame(
        {'radiation': grouped['radiation'].agg('sum'), 
         'tamb': grouped['tamb'].agg('mean'), 
         'new_column': grouped['tamb'].agg('count')})

print(using_agg(df))
np.random.seed(2016)

date_times = pd.date_range(DT.datetime(2012, 4, 5, 8, 0),
                           DT.datetime(2012, 4, 6, 12, 0),
                           freq='1min')
tamb = np.random.sample(date_times.size) * 10.0
radiation = np.random.sample(date_times.size) * 10.0
df = pd.DataFrame(data={'tamb': tamb, 'radiation': radiation},
                  index=date_times)
屈服

                     new_column   radiation      tamb
2012-04-05 08:00:00          60  279.432788  4.549235
2012-04-05 09:00:00          60  310.032188  4.414302
2012-04-05 10:00:00          60  257.504226  5.056613
2012-04-05 11:00:00          60  299.594032  4.652067
2012-04-05 12:00:00           1    8.109946  7.795668

注意我的第一个答案建议使用
groupby/apply

def using_apply(df):
    grouped = df.groupby(pd.TimeGrouper('1H'))
    result = grouped.apply(foo).unstack(-1)
    result = result.sortlevel(axis=1)
    return result[['radiation', 'tamb', 'new_column']]

def foo(grp):
    radiation = grp['radiation'].sum()
    tamb = grp['tamb'].mean()
    cnt = grp['tamb'].count()
    return pd.Series([radiation, tamb, cnt], index=['radiation', 'tamb', 'new_column'])
事实证明,在这里使用
apply
比使用
agg
慢得多。如果我们在1681行数据帧上使用_agg对
进行基准测试,而不是使用_apply
进行基准测试:

import datetime as DT
import numpy as np
import pandas as pd
np.random.seed(2016)

date_times = pd.date_range(DT.datetime(2012, 4, 5, 8, 0),
                           DT.datetime(2012, 4, 5, 12, 0),
                           freq='1min')
tamb = np.random.sample(date_times.size) * 10.0
radiation = np.random.sample(date_times.size) * 10.0
df = pd.DataFrame(data={'tamb': tamb, 'radiation': radiation},
                  index=date_times)

resampled = df.resample('1H', how={'radiation': np.sum, 'tamb': np.mean})
print(resampled[['radiation', 'tamb']])
#                       radiation      tamb
# 2012-04-05 08:00:00  279.432788  4.549235
# 2012-04-05 09:00:00  310.032188  4.414302
# 2012-04-05 10:00:00  257.504226  5.056613
# 2012-04-05 11:00:00  299.594032  4.652067
# 2012-04-05 12:00:00    8.109946  7.795668

def using_agg(df):
    grouped = df.groupby(pd.TimeGrouper('1H'))
    return pd.DataFrame(
        {'radiation': grouped['radiation'].agg('sum'), 
         'tamb': grouped['tamb'].agg('mean'), 
         'new_column': grouped['tamb'].agg('count')})

print(using_agg(df))
np.random.seed(2016)

date_times = pd.date_range(DT.datetime(2012, 4, 5, 8, 0),
                           DT.datetime(2012, 4, 6, 12, 0),
                           freq='1min')
tamb = np.random.sample(date_times.size) * 10.0
radiation = np.random.sample(date_times.size) * 10.0
df = pd.DataFrame(data={'tamb': tamb, 'radiation': radiation},
                  index=date_times)
我发现使用IPython的
%timeit
函数

In [83]: %timeit using_apply(df)
100 loops, best of 3: 16.9 ms per loop

In [84]: %timeit using_agg(df)
1000 loops, best of 3: 1.62 ms per loop
使用_agg
比使用_apply
和(基于其他
%timeit
测试)随着
len(df)
成长


顺便说一下,关于

frame.resample('1H', how={'radiation': np.sum, 'tamb': np.mean,\
               'new_column': count()})
除了
how
dict不接受不存在的列名这一问题外,
count
中的括号也有问题。
how
dict中的值应该是函数对象
count
是一个函数对象,但是
count()
是通过调用
count
返回的值

由于Python在调用函数之前对参数求值,
count()
frame.resample(…)
之前被调用,然后
count()
的返回值与绑定到
how
参数的dict中的键
'new\u column'
相关联。那不是你想要的


关于更新的问题:在调用
groupby/agg
之前,预先计算所需的值:

而不是

grouped = df.groupby(['name1',pd.TimeGrouper('M')])
return pd.DataFrame(
    {'new_col1': grouped['col1'][grouped['col1'] > 0].agg('sum')
     ...
# ImplementationError since `grouped['col1']` does not implement __getitem__
使用


有关为什么预计算有助于提高性能的更多信息,请参阅。

感谢您的详细而周到的解释。我真的很感激。答案教会了我很多。谢谢。问题:在foo(grp)中,每个聚合器每列操作的执行方式与聚合器的顺序计算方式是否有所不同。在我的例子中,foo(grp)中有30个聚合器,这需要很长时间,因为它必须在同一组组中一次遍历每个聚合器。不确定=的工作方式是否相同。我想知道是否有一种方法可以使计算速度矢量化?事实上,我认为我的第一个建议是使用
apply
。有一种更快的方法:使用
groupby/agg
而不是
groupby/apply
。我编辑了我的帖子来表达我的意思。非常感谢使用agg的解决方案。我很感激。似乎我在计算聚合器的方式上遇到了另一个问题。我想在单独的列中计算正负值的.agg('sum')。我在使用apply(foo)方法时能够做到这一点(但你知道这不是最优的)。你可能需要预先计算新列,其中一列中只有正值,另一列中只有负值。然后可以将
groupby/agg('sum')
应用于这些新列。