【问题标题】:python pandas rolling function with two arguments in a grouped DataFramepython pandas rolling函数在分组数据帧中有两个参数
【发布时间】:2017-01-18 09:35:53
【问题描述】:

这是对我之前的问题的某种扩展 python pandas rolling function with two arguments.

如何按组执行相同的操作?假设下面的“C”列用于分组。

我正在努力:

  1. 按“C”列分组
  2. 在每个组中,按“A”排序
  3. 对于每个组,将采用两个参数(如 kendalltau)的滚动函数应用于参数“A”和“B”。

预期的结果将是如下所示的 DataFrame:

我一直在尝试上面链接中描述的“传递索引”解决方法,但是这种情况的复杂性超出了我的技能:-(。这是一个玩具示例,与我正在使用的内容相距不远,所以为了简单起见,我使用了随机生成的数据。

rand = np.random.RandomState(1)
dff = pd.DataFrame({'A' : np.arange(20),
                    'B' : rand.randint(100, 120, 20),
                    'C' : rand.randint(0, 2, 20)})

def my_tau_indx(indx):
    x = dff.iloc[indx, 0]
    y = dff.iloc[indx, 1]
    tau = sp.stats.mstats.kendalltau(x, y)[0]
    return tau

dff['tau'] = dff.sort_values(['C', 'A']).groupby('C').rolling(window = 5).apply(my_tau_indx, args = ([dff.index.values]))

我所做的每一次修复都会产生另一个错误...

上述问题已由 Nickil Maveli 解决,它适用于 numpy 1.11.0、pandas 0.18.1、scipy 0.17.1 和 conda 4.1.4。它会产生一些警告,但可以正常工作。


在我的另一台机器上使用最新和最好的 numpy 1.12.0、pandas 0.19.2、scipy 0.18.1、conda 版本 3.10.0 和 BLAS/LAPACK - 它不起作用,我得到下面的回溯。这似乎与版本相关,因为我升级了第一台机器它也停止了工作......以科学的名义......;-)

正如 Nickil 所建议的,这是由于 numpy 1.11 和 1.12 之间的不兼容造成的。降级 numpy 有帮助。由于我在 Windows 上安装了 BLAS/LAPACK,因此我从 http://www.lfd.uci.edu/~gohlke/pythonlibs/ 安装了 numpy 1.11.3+mkl。

Traceback (most recent call last):

File "<ipython-input-4-bbca2c0e986b>", line 16, in <module>
t = grp.apply(func)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\groupby.py", line 651, in apply
return self._python_apply_general(f)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\groupby.py", line 655, in _python_apply_general
self.axis)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\groupby.py", line 1527, in apply
res = f(group)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\groupby.py", line 647, in f
return func(g, *args, **kwargs)

File "<ipython-input-4-bbca2c0e986b>", line 15, in <lambda>
func = lambda x: pd.Series(pd.rolling_apply(np.arange(len(x)), 5, my_tau_indx), x.index)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\stats\moments.py", line 584, in rolling_apply
kwargs=kwargs)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\stats\moments.py", line 240, in ensure_compat
result = getattr(r, name)(*args, **kwds)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\window.py", line 863, in apply
return super(Rolling, self).apply(func, args=args, kwargs=kwargs)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\window.py", line 621, in apply
center=False)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\window.py", line 560, in _apply
result = calc(values)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\window.py", line 555, in calc
return func(x, window, min_periods=self.min_periods)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\window.py", line 618, in f
kwargs)

File "pandas\algos.pyx", line 1831, in pandas.algos.roll_generic (pandas\algos.c:51768)

File "<ipython-input-4-bbca2c0e986b>", line 8, in my_tau_indx
x = dff.iloc[indx, 0]

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\indexing.py", line 1294, in __getitem__
return self._getitem_tuple(key)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\indexing.py", line 1560, in _getitem_tuple
retval = getattr(retval, self.name)._getitem_axis(key, axis=axis)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\indexing.py", line 1614, in _getitem_axis
return self._get_loc(key, axis=axis)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\indexing.py", line 96, in _get_loc
return self.obj._ixs(key, axis=axis)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\core\frame.py", line 1908, in _ixs
label = self.index[i]

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\indexes\range.py", line 510, in __getitem__
return super_getitem(key)

File "C:\Apps\Anaconda\v2_1_0_x64\envs\python35\lib\site-packages\pandas\indexes\base.py", line 1275, in __getitem__
result = getitem(key)

IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

最后的检查:

【问题讨论】:

  • 预期输出是什么?
  • @Andrew L - 谢谢,我错误地认为这可以推断出来。我希望现在更清楚了。

标签: python pandas


【解决方案1】:

实现的一种方法是遍历每个组并在每个这样的组上使用pd.rolling_apply

import scipy.stats as ss

def my_tau_indx(indx):
    x = dff.iloc[indx, 0]
    y = dff.iloc[indx, 1]
    tau = ss.mstats.kendalltau(x, y)[0]
    return tau

grp = dff.sort_values(['A', 'C']).groupby('C', group_keys=False)
func = lambda x: pd.Series(pd.rolling_apply(np.arange(len(x)), 5, my_tau_indx), x.index)
t = grp.apply(func)
dff.reindex(t.index).assign(tau=t)


编辑:

def my_tau_indx(indx):
    x = dff.ix[indx, 0]
    y = dff.ix[indx, 1]
    tau = ss.mstats.kendalltau(x, y)[0]
    return tau

grp = dff.sort_values(['A', 'C']).groupby('C', group_keys=False)
t = grp.rolling(5).apply(my_tau_indx).get('A')

grp.head(dff.shape[0]).reindex(t.index).assign(tau=t)

【讨论】:

  • 感谢您发布解决方案。由于pd.rolling_apply 将被弃用,我想知道是否有办法使用rolling 实现相同的效果?另外,(这更多是我的好奇心)您是否想到了一个不依赖于修改全局变量的函数的解决方案?
  • 我不认为DF.rolling().apply() 能够从当前形式的自定义函数返回标量值。另一种方法是使用滑动窗口列表理解重新设计它,然后逐行连接各种这样的计算,这似乎太费力了。最好暂时坚持使用pd.rolling_apply(),等到未来推出改进版或post an issue on github addressing this concern
  • IndexError 是由于 0.110.12 的 b/w 版本不兼容 numpy。如果可能的话,我会尝试找到一个修复程序,否则你现在可以只降级你的numpy 并且它会起作用。
  • 感谢您指向确切的模块!我降级了,它运行良好!如果可以的话,我会支持你 100 次!再次感谢您!
  • 由于我是从 R 中移植此代码,因此我将使用它来检查计算。由于数字问题,可能会有一些差异。例如:我记得在使用 JMP 结果作为指导开发 R 代码时,我看到了 R 和 JMP 之间的一些差异。
猜你喜欢
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2017-08-29
  • 2018-12-30
  • 2017-08-31
  • 1970-01-01
  • 2020-04-21
  • 2018-10-30
相关资源
最近更新 更多