【问题标题】:How do I transform a non-CSV text file into a CSV using Python/Pandas?如何使用 Python/Pandas 将非 CSV 文本文件转换为 CSV?
【发布时间】:2021-11-21 18:44:33
【问题描述】:

我有一个如下所示的文本文件:

身份证号:12345678
地点:1234561791234567090-8.9
街道:999 Street AVE
买家:john doe
身份证号:12345688
地点:3582561791254567090-8.9
街道:123 Street AVE
买家:Jane doe @ 买家 % LLC
身份证号:12345689
地点:8542561791254567090-8.9
街道:854 Street AVE
买家:Jake 和 Bob:Owner%LLC:Inc

我希望文件看起来像这样:

Id Number Location Street Buyer
12345678 1234561791234567090-8.9 999 Street AVE john doe
12345688 3582561791254567090-8.9 123 Street AVE Jane doe @ buyer % LLC
12345689 8542561791254567090-8.9 854 Street AVE Jake and Bob: Owner%LLC: Inc

我尝试了以下方法:

# 1 Read text file and ignore bad lines (lines with extra colons thus reading as extra fields).
tr = pd.read_csv('C:\\File Path\\test.txt', sep=':', header=None, error_bad_lines=False)

# 2 Convert into a dataframe/pivot table.
ndf = pd.DataFrame(tr.pivot(index=None, columns=0, values=1))

# 3 Clean up the pivot table to remove NaNs and reset the index (line by line).

nf2 = ndf.apply(lambda x: x.dropna().reset_index(drop=True))

这是最后一行 (#3):https://stackoverflow.com/a/62481057/10448224

当我执行上述操作并导出为 CSV 时,标题的排列方式如下:

(index) Street Buyer Id Number Location

数据填写得很好,但在某些时候买家字段变得不准确但其余字段在整个 DF 中都是准确的。

我的猜测:

当我运行脚本的 #1 部分时,我收到以下错误 507 次:

b'Skipping line 500: expected 2 fields, saw 3\nSkipping line 728: expected 2 fields, saw 3\

在新 DF 的末尾,我正好错过了 Byer 字段的 507 个条目。所以我认为当我放弃我的坏行时,该领域正在推动我的数据上升。

痛点:

Buyer 字段有时会包含额外的冒号和其他奇数字符。因此,当我尝试使用冒号作为分隔符时,我遇到了问题。

我是 Python 新手,对使用函数也很陌生。我主要使用 Pandas 来处理一些基本级别的数据。所以用伟大的迈克尔斯科特的话来说:“像我五岁一样向我解释。”非常感谢任何愿意提供帮助的人。

【问题讨论】:

  • 您应该手动将第一个冒号处的行拆分为:key,value = inputline.split(":",1) 将它们保存在字典中,每次点击"Id Number"(或文件末尾)将收集的字典附加到您的列表中,然后开始一本新词典。您可以很容易地弄清楚如何将该字典转换为数据框。
  • @RufusVS 你能否澄清这部分:key,value = inputline。对不起,我是 python 新手。我一般都知道字典是什么,但没有很多以这种方式使用它们的经验。
  • 您需要提供一些示例数据来展示疼痛问题,以便获得完整的答案。
  • @SupaDupa 关键是带有1个参数的split函数,它将:处的行分成两部分

标签: python pandas csv txt


【解决方案1】:

这就是我读入和使用拆分的意思。与其他答案非常相似。未经测试,我不记得输入行是否包含 eol,所以我也删除了它。

with open('myfile.txt') as f:
    data = []  # holds database
    record = {} # holds built up record
    for inputline in f:
        key,value = inputline.strip().split(':',1)
        if key == "Id Number": # new record starting
            if len(record):
                data.append(record) # write previous record
                record = {}
        record.update({key:value})
if len(record):
    data.append(record) # out final record
df = pd.DataFrame(data)

【讨论】:

  • 哇。这真的很近!收到此错误消息:Traceback (most recent call last): File "filepath\interactiveshell.py", line 3441, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-14-cf4eb6cb7fca>", line 5, in <module>key,value = inputline.strip().split(':',1) ValueError: not enough values to unpack (expected 2, got 1) 在较小的数据集子集上进行了尝试,并且成功了。但是,当我尝试使用更大的数据集时,出现上述错误。
  • 最好的猜测是字符串中没有':':'Id Number'.split(":") ['Id Number']。所以列表中没有项目可以解压到key,value 的value 部分。这就是为什么我要求提供数据示例。在任何情况下,您都需要添加代码来清理数据以使事情正常进行。
【解决方案2】:

这是一个演示基础知识的最小示例:

cat split_test.txt 

Id Number: 12345678
Location: 1234561791234567090-8.9
Street: 999 Street AVE
Buyer: john doe
Id Number: 12345688
Location: 3582561791254567090-8.9
Street: 123 Street AVE
Buyer: Jane doe @ buyer % LLC
Id Number: 12345689
Location: 8542561791254567090-8.9
Street: 854 Street AVE
Buyer: Jake and Bob: Owner%LLC: Inc

import csv 

with open("split_test.txt", "r") as f:
    id_val = "Id Number"
    list_var = []
    for line in f:
        split_line = line.strip().split(':')
        print(split_line)
        if split_line[0] == id_val:
            d = {}
            d[split_line[0]] = split_line[1]
            list_var.append(d)
        else:
            d.update({split_line[0]: split_line[1]})

list_var

[{'Id Number': ' 12345689',
  'Location': ' 8542561791254567090-8.9',
  'Street': ' 854 Street AVE',
  'Buyer': ' Jake and Bob'},
 {'Id Number': ' 12345678',
  'Location': ' 1234561791234567090-8.9',
  'Street': ' 999 Street AVE',
  'Buyer': ' john doe'},
 {'Id Number': ' 12345688',
  'Location': ' 3582561791254567090-8.9',
  'Street': ' 123 Street AVE',
  'Buyer': ' Jane doe @ buyer % LLC'}]

with open("split_ex.csv", "w") as csv_file:
    field_names = list_var[0].keys()
    csv_writer = csv.DictWriter(csv_file, fieldnames=field_names)
    csv_writer.writeheader()
    for row in list_var:
        csv_writer.writerow(row)

【讨论】:

    【解决方案3】:

    我会尝试逐行读取文件,将键值对拆分为dicts 列表,如下所示:

    data = [
      {
         "Id Number": 12345678,
         "Location": 1234561791234567090-8.9,
         ...
      },
      {
         "Id Number": ...
      }
    ]
    
    # easy to create the dataframe from here
    your_df = pd.DataFrame(data)
    

    【讨论】:

    • "我会尝试逐行读取文件,将键值对拆分成一个列表..." 我该怎么做?其他人提到使用键值对进行拆分,但我还是 python 新手。谢谢。
    猜你喜欢
    • 2023-03-28
    • 2018-11-24
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 2022-12-17
    • 2019-04-28
    • 2017-11-05
    • 1970-01-01
    相关资源
    最近更新 更多