使用groupby迭代和修改数据帧

2024-09-29 00:21:19 发布

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

我正在处理一个由1组成的大数组,需要系统地从数组的各个部分删除0。大数组由许多较小的数组组成,对于每个较小的数组,我需要用0替换其上下三角形。例如,我们有一个由索引值指示的具有5个子数组的数组(所有子数组的列数相同):

     0    1    2
0  1.0  1.0  1.0
1  1.0  1.0  1.0
1  1.0  1.0  1.0
2  1.0  1.0  1.0
2  1.0  1.0  1.0
2  1.0  1.0  1.0
3  1.0  1.0  1.0
3  1.0  1.0  1.0
3  1.0  1.0  1.0
3  1.0  1.0  1.0
4  1.0  1.0  1.0
4  1.0  1.0  1.0
4  1.0  1.0  1.0
4  1.0  1.0  1.0
4  1.0  1.0  1.0

我希望每组行在其上三角形和下三角形中进行修改,以便生成的矩阵为:

      0    1    2
0  1.0  1.0  1.0
1  1.0  1.0  0.0
1  0.0  1.0  1.0
2  1.0  0.0  0.0
2  0.0  1.0  0.0
2  0.0  0.0  1.0
3  1.0  0.0  0.0
3  1.0  1.0  0.0
3  0.0  1.0  1.0
3  0.0  0.0  1.0
4  1.0  0.0  0.0
4  1.0  1.0  0.0
4  1.0  1.0  1.0
4  0.0  1.0  1.0
4  0.0  0.0  1.0

目前我只使用numpy来实现这个结果数组,但是我认为我可以使用Pandas来加快它的速度。实际上,我的数据集非常大,几乎有500000行长。numpy代码如下:

import numpy as np

candidateLengths = np.array([1,2,3,4,5])
centroidLength =3

smallPaths = [min(l,centroidLength) for l in candidateLengths]

# This is the k_values of zeros to delete. To be used in np.tri
k_vals = list(map(lambda smallPath: centroidLength - (smallPath), smallPaths))
maskArray = np.ones((np.sum(candidateLengths), centroidLength))

startPos = 0
endPos = 0
for canNo, canLen in enumerate(candidateLengths):
    a = np.ones((canLen, centroidLength))
    a *= np.tri(*a.shape, dtype=np.bool, k=k_vals[canNo])
    b = np.fliplr(np.flipud(a))
    c = a*b

    endPos = startPos + canLen

    maskArray[startPos:endPos, :] = c

    startPos = endPos

print(maskArray)

当我在真实的数据集上运行这个程序时,执行它需要5-7秒。我认为这是由于这个巨大的for循环。如何使用熊猫分组来获得更高的速度?谢谢


Tags: 数据innumpyfornp数组速度三角形
1条回答
网友
1楼 · 发布于 2024-09-29 00:21:19

新答案

def tris(n, m):
    if n < m:
        a = np.tri(m, n, dtype=int).T
    else:
        a = np.tri(n, m, dtype=int)
    return a * a[::-1, ::-1]

idx = np.append(df.index.values, -1)
w = np.append(-1, np.flatnonzero(idx[:-1] != idx[1:]))
c = np.diff(w)
df * np.vstack([tris(n, 3) for n in c])

     0    1    2
0  1.0  1.0  1.0
1  1.0  1.0  0.0
1  0.0  1.0  1.0
2  1.0  0.0  0.0
2  0.0  1.0  0.0
2  0.0  0.0  1.0
3  1.0  0.0  0.0
3  1.0  1.0  0.0
3  0.0  1.0  1.0
3  0.0  0.0  1.0
4  1.0  0.0  0.0
4  1.0  1.0  0.0
4  1.0  1.0  1.0
4  0.0  1.0  1.0
4  0.0  0.0  1.0

旧答案

我定义了一些辅助三角形函数

def tris(n, m):
    if n < m:
        a = np.tri(m, n, dtype=int).T
    else:
        a = np.tri(n, m, dtype=int)
    return a * a[::-1, ::-1]

def tris_df(df):
    n, m = df.shape
    return pd.DataFrame(tris(n, m), df.index, df.columns)

那么

df * df.groupby(level=0, group_keys=False).apply(tris_df)

     0    1    2
0  1.0  1.0  1.0
1  1.0  1.0  0.0
1  0.0  1.0  1.0
2  1.0  0.0  0.0
2  0.0  1.0  0.0
2  0.0  0.0  1.0
3  1.0  0.0  0.0
3  1.0  1.0  0.0
3  0.0  1.0  1.0
3  0.0  0.0  1.0
4  1.0  0.0  0.0
4  1.0  1.0  0.0
4  1.0  1.0  1.0
4  0.0  1.0  1.0
4  0.0  0.0  1.0

相关问题 更多 >