Python 熊猫和列表理解的速度问题

Python 熊猫和列表理解的速度问题,python,pandas,list-comprehension,Python,Pandas,List Comprehension,我有一个包含400万行数据的数据集,我使用pd.read_csv(chunk size…)将其拆分为块,然后执行一些简单的数据清理代码,将其转换为我需要的格式 tqdm.pandas() print("Merging addresses...") df_adds = chunk.progress_apply(merge_addresses, axis = 1) [(chunk.append(df_adds[idx][0], ignore_index=True),chunk.append(df

我有一个包含400万行数据的数据集,我使用pd.read_csv(chunk size…)将其拆分为块,然后执行一些简单的数据清理代码,将其转换为我需要的格式

tqdm.pandas()
print("Merging addresses...")

df_adds = chunk.progress_apply(merge_addresses, axis = 1)

[(chunk.append(df_adds[idx][0], ignore_index=True),chunk.append(df_adds[idx][1], \
ignore_index=True)) for idx in tqdm(range(len(chunk))) \
if pd.notnull(df_adds[idx][0]['street_address'])]


def merge_addresses(row):
    row2 = pd.Series(
            {'Org_ID' : row.Org_ID,
            'org_name': row.org_name,
            'street_address': row.street_address2})
    row3 = pd.Series(
            {'Org_ID' : row.Org_ID,
            'org_name': row.org_name,
            'street_address': row.street_address3})
    return row2, row3
我正在使用TQM分析两个操作的速度,第一个是pandas apply函数在大约1.5k it/s的速度下运行良好,第二个是列表理解从大约2k it/s开始,然后迅速下降到200 it/s。有人能帮我解释一下如何提高速度吗

我的目标是将street_address 2和3合并并复制到street_address1列中,根据需要复制组织id和组织名称

更新

我试图捕获merge_地址中的任何nan,并将它们替换为字符串。我的目标是将address2和address3放入与address1位于同一列中的自己的行中(带有组织名称和组织id(因此这两个字段将是重复的)。因此,同一组织id可能有三行,但地址不同

df_adds = chunk.progress_apply(merge_addresses, axis = 1)

[(chunk.append(x[0]), chunk.append(x[1])) for x in tqdm(df_adds) if (pd.notnull(x[0][3]),pd.notnull(x[0][3]))]

def merge_addresses(row):
    if pd.isnull(row.street_address2):
        row.street_address2 = ''
    if pd.isnull(row.street_address3):
        row.street_address3 = ''
    return ([row.Org_ID, row.pub_name_adj, row.org_name, row.street_address2], [row.Org_ID, row.pub_name_adj, row.org_name, row.street_address3])

调用数据帧时出现错误

迭代地将行附加到数据帧可能比单个连接更需要计算。更好的解决方案是将这些行附加到列表中,然后一次将列表与原始数据帧连接起来


如果可以,请使用
pd.concat
以实现更快的实现。

正如注释中所证明的,此处的瓶颈是由于创建和馈送太多对象而造成的,这会消耗太多内存。此外,创建对象会消耗内存分配时间并降低速度

在100k数据集上证明:

# create sample dataframe
s = []
for i in range(100000):
    s.append(tuple(['name%d' %i, 'a%d' %i, 'b%d' %i]))

labels = ['name', 'addr1', 'addr2']
df = pd.DataFrame(s, columns=labels)

# addr1, addr2 to addr
s = []
for k in ['addr1', 'addr2']:
    s.append(df.filter(['id', 'name', k]).rename(columns={k:'addr'}))
result = pd.concat(s)

df.append
比list的内置
append
慢得多。示例在几秒钟内完成。

df\u adds[idx]
是一个复杂的对象,占用大量内存。因此,当数百万个对象附加到数据帧/列表中时,操作会减慢。请尝试使用内置类型(str,int)而不是对象。在这种情况下,用更简单的行替换pd.Series。对象不仅包含数据(street_address),还包含方法字典和对自身的引用。因此,它不仅仅是一个“原语”数据。无需存储pd.Series列表,您可以用一个pd.Series替换pd.Series列表,并使用所需的cols。谢谢-我在merge_addresses()中替换了pd.Series仅使用字典。it/s总体上有所增加,但在操作中仍然会出现30%左右的减速。我可以确认列表理解本身看起来不错吗?我对这些很陌生。@knh190您介意将此作为答案写出来吗?chunk.append(df_添加[x][0])部分给出了错误:
RuntimeWarning:'@DavidM这是由
str
int
之间的比较引起的,它们是不可比较的。我想它是由
如果不是x[-1]
引起的。如果pd.notnull(x[-1]),则是由
引起的
为你工作?@DavidM或我认为你需要更新你的代码。我现在不知道是什么。我更新了我的问题以向你展示。我尝试捕获合并地址中的任何NaN并将其替换为字符串。我的目标是将address2和address3放在它们自己的行中(带有组织名称和组织id)(因此这两个字段将是重复的)与address1位于同一列中。因此同一组织id可能有三行,但地址不同。@DavidM很抱歉更新太晚!如果还有任何问题,请参阅最新的答案。(注意,我刚才注意到,为什么要将新记录附加到现有的
区块
?)