【问题标题】:Fastest way to process all rows and columns in a Pandas dataframe?处理 Pandas 数据框中所有行和列的最快方法?
【发布时间】:2023-02-08 03:19:34
【问题描述】:

我有一种方法可以从 MySQL 表中提取信息并将其传递给数据框。然后我逐列检查 DF 中的所有项目,看它们是否包含前缀,如果包含,则对其进行解密。知道如何尽可能快地运行它吗?

我可以看出这是一种非常低效的处理方式,但对于超过 400,000 行的大表来说,这已成为一个问题。它有第二次检查,因为一些数据被解密了两次,我想可能有一种更优雅的递归方式来执行此操作......

for i in df.index:
        for c in df.columns:
            if type(df.loc[i, c]) == str:
                if "Crypt#" in df.loc[i, c]:
                    df.loc[i, c] = decrypt_data(df.loc[i, c])
                    if "Crypt#" in df.loc[i, c]:
                        df.loc[i, c] = decrypt_data(df.loc[i, c])
return df

【问题讨论】:

  • 你能给我们更多关于你的 df 的信息,它是如何以及你想要的输出吗?
  • 嗨 Emanuele,在这种情况下,DF 是一系列交易。许多不同类型的列都被加密了,但表之间并不一致,这就是为什么我们要检查列中的数据是否包含加密前缀。输出应该完全相同,除了包含解密数据的列被解密。
  • @atomey 各种列的数据类型是什么?列的格式/结构是否正确(如果列中有任何str,则整个列都是str)?或者在给定的列/行中,您是否混合了不同的数据类型?
  • 如果数据是混合的,第一步应该是通过(一些已知的标记?)过滤它,以便它是格式/结构良好的
  • 您能否提供decrypt_data功能的操作细节?还是(就 StackOverflow 而言)是一个“黑匣子”功能?

标签: pandas dataframe


【解决方案1】:

所以这就是我对问题的理解,你想在df的所有单元格的值上使用decrypt_data(),如果它们是str并且有Crypt#的前缀。

虽然我不确定这会提供更多性能,但最简单的方法包括使用 pd.applymapnp.vectorizepd.apply

# dummy DataFrame
df = pd.DataFrame(
    {'col1': np.random.choice(["Crypt#", "string", "int"], 10),
     'col2': np.random.choice(["Crypt#", "string", "int"], 10)}
)

def _decrypt(string):
    if string.startswith('Crypt#'):
        return decrypt_data(string)
    else:
        return string

# dummy decrypt_data func
def decrypt_data(string):
    return string+"decrypt"

然后你可以使用:

df.applymap(_decrypt)

或者

df.apply(np.vectorize(_decrypt))

示例输出:

            col1            col2
0  Crypt#decrypt         string
1         string  Crypt#decrypt
2  Crypt#decrypt            int

这假设列中的所有值都属于同一类型,否则您需要考虑这一点。

在性能方面,我们可以将这些函数与您的原始代码 sn-p 进行比较,发现虽然有一些增益,但它是边际的并且实际上与 np.vectorize 方法相同(应该注意 in the np.vectorize docs 它声明它主要是为了方便和有效的 for 循环)。 这是因为您无法轻松地将自定义函数矢量化。

import perfplot
import pandas as pd
import numpy as np


# Your version made into a function
def original_func(df):
    for i in df.index:
        for c in df.columns:
            if type(df.loc[i, c]) == str:
                if "Crypt#" in df.loc[i, c]:
                    df.loc[i, c] = decrypt_data(df.loc[i, c])
    return df

def original(df):
    return original_func(df)
def applymap(df):
    return df.applymap(numpy_decrypt)
def np_vectorize(df):
    return df.apply(np.vectorize(numpy_decrypt))

perfplot.show(
    setup=lambda n: pd.DataFrame({'strings1': np.random.choice(["Crypt#_string", "string2", "4"], n),
                                'string2': np.random.choice(["Crypt#_string", "string2", "4"], n)}),
    kernels=[
        lambda df: original(df),
        lambda df: applymap(df),
        lambda df: np_vectorize(df)],
    
    labels=['applymap', 'np_vectorize', 'original'],
    n_range=[2 ** k for k in range(1, 20)],
    equality_check=None,  
    xlabel='~N Groups'
)

【讨论】:

    猜你喜欢
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    相关资源
    最近更新 更多