【问题标题】:Groupby group as argument to groupby apply to speed upGroupby 组作为 groupby 的参数适用于加速
【发布时间】:2020-10-02 01:53:34
【问题描述】:

我有这个数据框a

    Dim1  Dim2  Dim3  Dim4  id
0      1     2     7    15   1
1      1    10    12     2   1
2      9    19    18    16   1
3      4     2     4    15   1
4      8     1     9     5   1
5     14    18     3     2   1
6     19    19    19    17   1
7     14    18     3     2   1
8     85    16    35    61   2
9     71    13     7     4   2
10    74     1     2    81   2
11    50    25    19    85   2
12    74     1    37    31   2
13    21    57    51    13   2
14    25    80    51    47   2
15    91    34    30    75   2
16    34    77    10    76   2
17    84    98    25    33   2
18    82    69    24    44   2
19    88    44    74    31   2

我正在尝试将函数 f 应用于每个 id 组和每一行。我是这样写的

def f(row, df):
    
    group = row["id"]
    df = df.query("id == @group")
    # keep only columns we need
    
    
    #filter for all rows where none of the columns are worse
    df = df[(row <= df).all(axis = 1)]
    #filter for rows where any column is better.
    df = df[(row < df).any(axis = 1)]
    
    count = len(df)
    return count

当我执行a.apply(f, args = [a], axis = 1) 时它会起作用。结果是

0     2
1     2
2     1
3     2
4     2
5     1
6     0
7     1
8     0
9     5
10    0
11    0
12    1
13    1
14    0
15    0
16    0
17    0
18    0
19    0
dtype: int64

但是,我认为可能有一种方法可以编辑我的函数,这样我就不会像您在下面看到的那样进行重复过滤,将该函数逐行应用于a.groupby("id")

def f(row, df):
    
    group = row["id"]
    df = df.query("id == @group")
    ...

我查看了this question,但没有找到我正在寻找的答案。如何将 groupby 对象本身添加到函数中并按行执行?

【问题讨论】:

  • 这个数据集的预期输出是什么?
  • 我添加了输出

标签: python pandas pandas-groupby


【解决方案1】:

让我们在id 上尝试交叉合并并查询:

features = df.columns[:-1]

(df.assign(counter=df.index)
   .merge(df, on='id')
   .query(' and '.join([f'{col}_x<={col}_y' for col in features]))
   .query(' or '.join([f'{col}_x<{col}_y' for col in features]))
   .groupby('counter')['id']
   .count()
   .reindex(df.index, fill_value=0)
)

输出:

0     2
1     2
2     1
3     2
4     2
5     1
6     0
7     1
8     0
9     5
10    0
11    0
12    1
13    1
14    0
15    0
16    0
17    0
18    0
19    0
Name: id, dtype: int64

更新:根据您的评论:

features = df.columns[:-1]

def myfunc(d):
    a = d[features].values
    diff = a[:,None,:] - a
    out = (diff<=0).all(-1) & (diff<0).any(-1)
    return pd.Series(out.sum(-1), index=d.index)

df.groupby('id').apply(myfunc)

输出(注意一级索引是原始数据帧的索引):

id    
1   0     2
    1     2
    2     1
    3     2
    4     2
    5     1
    6     0
    7     1
2   8     0
    9     5
    10    0
    11    0
    12    1
    13    1
    14    0
    15    0
    16    0
    17    0
    18    0
    19    0
dtype: int64

【讨论】:

  • 谢谢!。是的,它有效,但我正在专门寻找一种将解决方案转换为a.groupby.apply 类型的方法。因为我有很多这样的功能,我无法重写它们中的每一个。我当然会赞成你的回答
  • @EmilMirzayev 当然,请参阅更新。通常,当您必须将每一行与同一组中的所有行进行比较时,我们会考虑交叉合并或 groupby。
猜你喜欢
  • 1970-01-01
  • 2021-03-18
  • 1970-01-01
  • 2021-09-19
  • 2018-09-19
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
相关资源
最近更新 更多