首页 > 解决方案 > 使用 Pandas 提高文本文件处理的效率

问题描述

我有一个文本文件,其中包含超过 100 万个观察值,我正在尝试将其处理成数据框。问题是它看起来像这样:

product/productId: blah blah
product/title: blue shirt
product/price: unknown
review/userId: blah blah
review/text: blah blah

product/productId: blah blah
product/title: pair of jeans
product/price: unknown
review/userId: blah blah
review/text: blah blah

每个文本块都是一个独特的观察,我必须将它们分组并在一个整洁的数据框中将它们排成行。所以总而言之,这是需要处理的超过 500 万行。

我对 Python 还很陌生,所以我不太确定清理它的最佳方法是什么。我首先将文件读入 Pandas df:

initialData = pd.read_csv(args["data_file"], sep="\n", header=None, dtype=str)
initialData.columns = [ "data" ]

print(initialData.head(5), "\n\n", initialData.shape)

输出:

                                                data
0                      product/productId:  blah blah
1   product/title: blah blah
2                             product/price: unknown
3                      review/userId: blah blah
4   review/profileName: blah blah

 (5819330, 1)

然后我尝试使用以下函数将每行中的数据组织到具有命名列的相应行中:

def organize_data(df):
    df["col"] = 0
    # group lines by observation represented
    for line_count in range(0, len(df), 10):
        indices = [ line_count, line_count + 1, line_count + 2,
                    line_count + 3, line_count + 4, line_count + 5,
                    line_count + 6, line_count + 7, line_count + 8, line_count + 9 ]
        # iterate through grouped lines
        for index in indices:
            row = df.iloc[index]
            # split inputs, assign one to "col" column
            # that'll be used to assign each value to its
            # respective column
            split_row = row["data"].split(" ", 1)
            new_label = split_row[0]
            last_split = new_label.split("/")
            future_col_name = last_split[1]
            row["col"] = future_col_name
    organized_df = df.pivot(columns="col", values="data")

    return organized_df

正如您可以想象的那样,考虑到它几乎遍历文件中的每一行,它的速度非常慢。它给了我一个 SettingWithCopyWarning 来启动,所以当它完成时它甚至不会做我想做的事情。我该如何处理这些问题?

标签: pythonpandasdata-cleaning

解决方案


您可以对数据进行一些预处理,而不是使用 read_csv。我建议集合模块中的 defaultdict 将列表中的所有列分组。然后我们可以将 defaultdict 传递给 DataFrame 构造函数以获得最终输出:

from collections import defaultdict
import pandas as pd

with open('reviews.txt', 'r') as f:
    lines = f.readlines()
    data = defaultdict(list)
    for line in lines:
        col,value = line.split(':')
        data[col.strip()].append(value.strip())

    df = pd.DataFrame(data)
    print(df)

   product/productId  product/title product/price review/userId review/text
0          blah blah     blue shirt       unknown     blah blah   blah blah
1          blah blah  pair of jeans       unknown     blah blah   blah blah

推荐阅读