在熊猫数据框中的多行上有效地找到形状

时间:2020-01-31 14:37:12

标签: python python-3.x pandas

这是关于有效地在熊猫数据框中找到“ 2D形状”。我们生成了这样的框架:

l = ['>','<','v','^']

def gendf(r,c): 
    return pd.DataFrame(np.random.choice(l,size=(r,c)),columns=[i for i in range(c)])

我正在寻找以下形状:

    ^
<   ?   >
    v

带有“?”是任何角色。我有一个效率很低的嵌套循环,可以慢慢地完成工作:

def co(df):
    c=[]
    for i in list(df.index)[:-2]:
        for j in list(df.columns)[1:-1]:
            if df.loc[i,j]=='^':
                if df.loc[i+2,j]=='v' and df.loc[i+1,j-1]=='<' and df.loc[i+1,j+1]=='>':
                    c.append((i,j))
    return c

它只是寻找“顶部”,并在找到它时检查其余部分。作为嵌套循环,它非常慢-任何功能都可以让我更有效地执行此操作吗?

编辑:给定方法的计时器

%timeit co(df)
8.08 s ± 260 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit x1(df) #Chris A's method
1.89 s ± 102 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit x2(df) #sampers' method
6.22 s ± 289 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

让我知道是否还有更好的方法-这已经很有帮助了!

2 个答案:

答案 0 :(得分:4)

IIUC,您可以使用numpy.argwhereDataFrame.shift在多个布尔条件下尝试DataFrame.eq

Object

[出]

add(List)

答案 1 :(得分:1)

将所有内容投射到列表上在计算上很繁琐。使用iat获取1个元素也比loc快。

按照您要求的禁食解决方案,尽管它可能不是最干净的解决方案:

def search(df):
    result = []
    for i in range(z.shape[0] - 2):
        for j in range(1, z.shape[1] - 1):
            if z.iat[i,j] == '^' and z.iat[i+2, j]=='v' and z.iat[i+1 ,j-1]=='<' and z.iat[i+1, j+1]=='>':
                result.append((i+1,j))
    return result

将其与其他解决方案进行计时:

%timeit other_solution(df)
2.67 s ± 152 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit search(df)
12.4 ms ± 836 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)