首页 > 解决方案 > 从多索引中选择时如何避免链式应用?

问题描述

我有一个这样的数据框:

import numpy as np
import pandas as pd


df = pd.DataFrame({
    'ind1': list('AAABBBCCC'),
    'ind2': list(map(int, list('123123123'))),
    'val1': [0, 1, 2, -1, -4, -5, 10, 11, 4],
    'val2': [0.1, 0.2, -0.2, 0.1, 0.2, 0.2, -0.1, 2, 0.1]
})

df = df.set_index(['ind1', 'ind2'])

           val1  val2
ind1 ind2            
A    1        0   0.1
     2        1   0.2
     3        2  -0.2
B    1       -1   0.1
     2       -4   0.2
     3       -5   0.2
C    1       10  -0.1
     2       11   2.0
     3        4   0.1

我想选择其中值之间的差异的绝对值val1正在增加的所有条目。

我目前这样做如下:

m_incr = (
    df.groupby('ind1')['val1']
      .apply(lambda x: np.diff(abs(x)))
      .apply(lambda x: all(eli > 0 for eli in x))
)

df_incr = df[m_incr[df.index.get_level_values('ind1')].values]

这给了我想要的结果:

           val1  val2
ind1 ind2            
A    1        0   0.1
     2        1   0.2
     3        2  -0.2
B    1       -1   0.1
     2       -4   0.2
     3       -5   0.2

我的问题是是否有一种更直接/有效的方法可以避免链式applys。

标签: pythonpandasdataframeselectmulti-index

解决方案


用于与原始尺寸相同GroupBy.transform的退货:SeriesDataFrame

mask = df.groupby('ind1')['val1'].transform(lambda x: (np.diff(abs(x)) > 0).all())

然后通过掩码过滤boolean indexing

print (df[mask])

全部一起:

print (df[df.groupby('ind1')['val1'].transform(lambda x: (np.diff(abs(x)) > 0).all())])

           val1  val2
ind1 ind2            
A    1        0   0.1
     2        1   0.2
     3        2  -0.2
B    1       -1   0.1
     2       -4   0.2
     3       -5   0.2

详情

print (mask)
ind1  ind2
A     1        True
      2        True
      3        True
B     1        True
      2        True
      3        True
C     1       False
      2       False
      3       False
Name: val1, dtype: bool

推荐阅读