【问题标题】:Parsing a semi colon delimited file in python to create a CSV在 python 中解析以分号分隔的文件以创建 CSV
【发布时间】:2012-12-22 06:36:14
【问题描述】:

我有一个以下格式的大文本文件,我希望将其转换为 CSV 文件。 CSV 文件中的列名应该与下面看到的元组的第一部分相对应。可以安全地假设该行中的第一项(不是元组)将始终采用以下格式。

其他问题包括每行可能没有相同的字段 - 例如,有些有状态,有些则没有。有些有同一个字段的多个实例,在这种情况下,我需要连接元组的第二部分(例如 To Mr Smith;Mrs Green),但这些问题目前还很遥远。

[' Message  1 '];['Status', 'Read'];['Message ID', '012434'];['Message Truncation', 'OK'];['Priority', 'Low'];['Sent Time', '15/12/2010 05:56:36']
[' Message  2 '];['ColumnName', 'Read'];['ColumnName2', '012434'];['Message Truncation', 'OK'];['Priority', 'Low'];['Sent Time', '15/12/2010 05:56:36']
[' Message  3 '];['To', 'Mr Smith'];['To', 'Mrs green'];['Message Truncation', 'OK'];['Priority', 'Low'];['Sent Time', '15/12/2013 05:56:36']

...

我的计划是遍历文件中的每个块以建立列名,然后开始向这些列名添加数据,并在适当的时候留空。我只是想知道如何以 Python 的方式解决这个问题,因为我玩弄了一个字典列表并卡住了。

我想我需要拆分行,然后将每个元组添加到字典中。有什么帮助吗? 谢谢!

for line in file:
    line_split = line.split(';')

【问题讨论】:

    标签: python list csv dictionary tuples


    【解决方案1】:

    您可以使用ast.literal_eval 将每个['something', 'something_else'] 块转换为python 列表:

    import ast
    
    column_ids = set()
    
    for line in file:
        columns = [tuple(ast.literal_eval(c)) for c in line.split(';')]
        columns[0] = ('id', columns[0][0]) # Give the first column a 'Id' key
        columns = dict(columns)  # turn the row into a dict
        column_ids.update(columns)
    

    添加一个打印语句并使用您的示例输入,结果是:

    {'Status': 'Read', 'Sent Time': '15/12/2010 05:56:36', 'Message Truncation': 'OK', 'Message ID': '012434', 'Priority': 'Low', 'id': ' Message  1 '}
    {'Sent Time': '15/12/2010 05:56:36', 'ColumnName2': '012434', 'Message Truncation': 'OK', 'Priority': 'Low', 'ColumnName': 'Read', 'id': ' Message  2 '}
    {'Message Truncation': 'OK', 'To': 'Mrs green', 'Priority': 'Low', 'id': ' Message  3 ', 'Sent Time': '15/12/2013 05:56:36'}
    

    而column_ids 是:

    set(['Status', 'Priority', 'ColumnName', 'Message Truncation', 'Message ID', 'To', 'Sent Time', 'ColumnName2', 'id'])
    

    【讨论】:

    • 而他们,O.P. 可以创建一组所有 dict 键来获取 csv 文件的列标题 - 就像在 columns = sorted( set(key for key in itertools.chain(*(dct.keys() for dct in messages))))
    • @jsbueno: 或者您保留一组列 ID,如更新的示例中所示。
    【解决方案2】:

    使用纯python的解决方案...

    infile = "listdata.txt"
    data = open(infile, "r").readlines()
    
    dataDict = []
    columns = []
    
    # Create a dictionary list
    for line in data:
        row = line.split(";");
        rowData = {}
        for cell in row:
            cell = cell.strip()[1:-1].split(",")
            if len(cell) > 1:
                rowData[cell[0].strip().strip('"').strip("'")] = cell[1].strip().strip('"').strip("'")
        keys = rowData.keys()
        dataDict.append(rowData)
        columns = list(set(columns) | set(keys))
    
    # Write dictionary list to file
    outfile = "listdata.csv"
    fp = open(outfile, "w")
    
    for key in columns:
        fp.write(key + ", ")
    
    fp.write("\n")
    
    for data in dataDict:
        for key in columns:
            if key in data:
                fp.write(data[key] + ",")
            else:
                fp.write(",")
        fp.write("\n")
    
    fp.close()
    

    输入:

    [' Message  1 '];['Status', 'Read'];['Message ID', '012434'];['Message Truncation', 'OK'];['Priority', 'Low'];['Sent Time', '15/12/2010 05:56:36']
    [' Message  2 '];['ColumnName', 'Read'];['ColumnName2', '012434'];['Message Truncation', 'OK'];['Priority', 'Low'];['Sent Time', '15/12/2010 05:56:36']
    [' Message  3 '];['To', 'Mr Smith'];['To', 'Mrs green'];['Message Truncation', 'OK'];['Priority', 'Low'];['Sent Time', '15/12/2013 05:56:36']
    

    输出:

    Status, Sent Time, To, ColumnName2, Message ID, Message Truncation, Priority, ColumnName, 
    Read,15/12/2010 05:56:36,,,012434,OK,Low,,
    ,15/12/2010 05:56:36,,012434,,OK,Low,Read,
    ,15/12/2013 05:56:36,Mrs green,,,OK,Low,,
    

    更新

    这会处理具有相同类型的多个条目,然后使用":" 连接。

    key = cell[0].strip().strip('"').strip("'")
    value = cell[1].strip().strip('"').strip("'")
    if key in rowData:
        rowData[key] = rowData[key] + ":" + value
    else:
        rowData[key] = value
    

    【讨论】:

    • 分隔符应该是什么?
    • 这太棒了,谢谢!!我想通过说经常使事情复杂化,一行将有多个“到”单元格。在这种情况下,我希望最终的 CSV 文件只获取收件人的分隔列表:人员。 (参见示例中的消息 3)我一直在玩,我必须对 dataDict.append(rowData) 行进行更改,因为我假设当它似乎是第二个“To”条目时,它会覆盖第一个?另外,我决定对 Column 列表进行硬编码,因为事实证明我真的只对 9 个左右的列感兴趣。
    【解决方案3】:

    使用熊猫:

    from pandas import *
    import ast
    from itertools import chain
    
    df=read_csv('in.txt',sep=';',header=None).applymap(ast.literal_eval).ix[:,1:]
    newdf=DataFrame(columns=set(i[0] for i in chain(*df.values)),index=df.index)
    
    for row in df.iterrows():   
        for c in row[1].values:
            newdf[c[0]][row[0]]=c[1]      
    
    newdf.to_csv('out.csv')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-20
      • 1970-01-01
      • 2019-09-26
      • 2016-05-25
      • 2014-12-31
      • 1970-01-01
      • 2018-03-22
      • 2017-02-09
      相关资源
      最近更新 更多