有没有比groupby更快的方法来遍历组?

2024-03-28 20:04:38 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我把前面的一个问题缩小到了这个范围:我有一个类似这样的数据帧

              id  temp1  temp2
    9       10.0   True  False
    10      10.0   True  False
    11      10.0  False   True
    12      10.0  False   True
    17      15.0   True  False
    18      15.0   True  False
    19      15.0   True  False
    20      15.0   True  False
    21      15.0  False  False
    33      27.0   True  False
    34      27.0   True  False
    35      27.0  False   True
    36      27.0  False  False
    40      31.0   True  False
    41      31.0  False   True 
               .
               .
               .

实际上,它有几百万行长(还有其他一些列)。你知道吗

我现在做的是

    grouped = coinc.groupby('id')
    final = grouped.filter(lambda x: ( x['temp2'].any() and x['temp1'].any()))
    lanif = final.drop(['temp1','temp2'],axis = 1 )

(coinc是数据帧的名称)

只有当temp1和temp2中的某些具有相同id的行都为true时,它才保留行(按id分组)。例如,对于上面的数据帧,它将删除具有id 15的行,但保留其他所有行。你知道吗

然而,这是致命的缓慢,我想知道是否有一个更快的方法来做到这一点。你知道吗


Tags: and数据lambdaidfalsetrueanyfilter
3条回答

问题不在于groupby,而在于lambda。Lambda操作没有矢量化*。使用agg可以更快地得到相同的结果。我会做:

 groupdf = coinc.groupby('id').agg(any)
 # Selects instance where both contain at least one true statement
 mask = maskdf[['temp1','temp2']].all(axis=1) 
 lanif = groupdf[mask].drop(['temp1','temp2'],axis = 1 )

*这是一个非常微妙的问题,我认为过于简单化了,抱歉。你知道吗

i, u = pd.factorize(coinc.id)
t = np.zeros((len(u), 2), bool)
c = np.column_stack([coinc.temp1.to_numpy(), coinc.temp2.to_numpy()])

np.logical_or.at(t, i, c)

final = coinc.loc[t.all(1)[i], ['id']]

final

      id
9   10.0
10  10.0
11  10.0
12  10.0
33  27.0
34  27.0
35  27.0
36  27.0
40  31.0
41  31.0

在这里使用filter和lambda函数会大大降低速度。你可以通过移除它来加快速度。你知道吗


u = coinc.groupby('id')
m = u.temp1.any() & u.temp2.any()
res = df.loc[coinc.id.isin(m[m].index), ['id']]

在更大的框架上比较这个方法。你知道吗

a = np.random.randint(1, 1000, 100_000)
b = np.random.randint(0, 2, 100_000, dtype=bool)
c = ~b

coinc = pd.DataFrame({'id': a, 'temp1': b, 'temp2': c})

In [295]: %%timeit
     ...: u = coinc.groupby('id')
     ...: m = u.temp1.any() & u.temp2.any()
     ...: res = coinc.loc[coinc.id.isin(m[m].index), ['id']]
     ...:
13.5 ms ± 476 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [296]: %%timeit
     ...: grouped = coinc.groupby('id')
     ...: final = grouped.filter(lambda x: ( x['temp2'].any() and x['temp1'].any()))
     ...: lanif = final.drop(['temp1','temp2'],axis = 1 )
     ...:
527 ms ± 7.91 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

np.array_equal(res.values, lanif.values)

True

相关问题 更多 >