【问题标题】:Split one column in CSV file into multiple columns while grouping the data in Python (without Pandas)将 CSV 文件中的一列拆分为多列,同时在 Python 中对数据进行分组(没有 Pandas)
【发布时间】:2018-04-26 06:02:58
【问题描述】:

我目前正在学习 Python,并希望对我的一个问题寻求帮助。我有一个 ”;”我正在尝试以 excel 和 csv 格式刷并提取一些数据的分离文件(如下所示)。

我的原始 CSV 文件..

    COUNTRY  COUNTRY_TIME            COUNTRY_REF        PRODUCT
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221     APPLE%BOX%LYON%022018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221     APPLE%BOX%LYON%032018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221     APPLE%BOX%LYON%052018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221     APPLE%BOX%LYON%062018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221     APPLE%BOX%NICE%032018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221    APPLE%BOX%LILLE%022018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221    APPLE%BOX%NEM%022018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221    APPLE%COVER%CWF%022018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221   APPLE%COVER%FZF%022018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221   APPLE%COVER%MX1%022018
    FRANCE  FRANCE20180222.16.30.00  FRANCE20180221 APPLE%BIGBOX%DIJON%022018
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%BODEN%012019
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%BODEN%022019
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%BODEN%032018
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%BODEN%042018
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%BODEN%052018
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%BODEN%062018
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%FLEN%012019
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%FLEN%032018
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%FLEN%042018
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%FLEN%052018
    SWEDEN  SWEDEN20180223.02.11.00  SWEDEN20180222 APPLE%SMALLBOX%FLEN%062018

我的最终预期数据应该是这样的,

COUNTRY EXCHANGE_CODE   TOWN_CODE   MONTH_CODE
FRANCE  BOX              LYON       022018;032018;052018;062018
FRANCE  BOX              NICE       032018
FRANCE  BOX              LILLE      022018
FRANCE  BOX              NEM        022018
FRANCE  COVER            CWF        022018
FRANCE  COVER            FZF        022018
FRANCE  COVER            MX1        022018
FRANCE  BIGBOX           DIJON      022018
SWEDEN  SMALLBOX         BODEN      012019;022019;032018;042018;052018;062018
SWEDEN  SMALLBOX         FLEN       012019;032018;042018;052018;062018

我已经创建了下面的脚本,但只能实现到下面给定的表格。

import csv
import os
from collections import defaultdict, OrderedDict
import itertools
from operator import itemgetter

in_path = os.path.expanduser("~/Desktop/FUTURES.csv")
out_path = os.path.expanduser("~/Desktop/Finalresult.csv")

with open(in_path, 'r') as f_in, open(out_path, 'w', newline='') as f_out:
    csv_reader = csv.reader(f_in, delimiter=';')
    writer = csv.writer(f_out)

    all = []
    row = next(csv_reader)
    row.append('LFU')
    row.append('EXCHANGE_CODE')
    row.append('TOWN_CODE')
    row.append('MONTH_CODE')
    all.append(row)

    for row in csv_reader:
        if row[0] in ['FRANCE', 'SWEDEN']:

            row.append(row[3].split('%')[0])
            row.append(row[3].split('%')[1])
            row.append(row[3].split('%')[2])
            row.append(row[3].split('%')[3])
            all.append(row)

    writer.writerows(map(itemgetter(0, 5, 6, 7), all))

我目前的结果..

COUNTRY FRUIT   EXCHANGE_CODE   TOWN_CODE   MONTH_CODE
FRANCE  APPLE   BOX                 LYON    022018
FRANCE  APPLE   BOX                 LYON    032018
FRANCE  APPLE   BOX                 LYON    052018
FRANCE  APPLE   BOX                 LYON    062018
FRANCE  APPLE   BOX                 NICE    032018
FRANCE  APPLE   BOX                 LILLE   022018
FRANCE  APPLE   BOX                 NEM     022018
FRANCE  APPLE   COVER               CWF     022018
FRANCE  APPLE   COVER               FZF     022018
FRANCE  APPLE   COVER               MX1     022018
FRANCE  APPLE   BIGBOX              DIJON   022018
SWEDEN  APPLE   SMALLBOX            BODEN   012019
SWEDEN  APPLE   SMALLBOX            BODEN   022019
SWEDEN  APPLE   SMALLBOX            BODEN   032018
SWEDEN  APPLE   SMALLBOX            BODEN   042018
SWEDEN  APPLE   SMALLBOX            BODEN   052018
SWEDEN  APPLE   SMALLBOX            BODEN   062018
SWEDEN  APPLE   SMALLBOX            FLEN    012019
SWEDEN  APPLE   SMALLBOX            FLEN    032018
SWEDEN  APPLE   SMALLBOX            FLEN    042018
SWEDEN  APPLE   SMALLBOX            FLEN    052018
SWEDEN  APPLE   SMALLBOX            FLEN    062018

如果能得到任何帮助,我将不胜感激。

P.S - 我不想使用 Pandas,Numpy。

【问题讨论】:

  • 您不应该在遍历它时写入行。这可能会导致意想不到的结果。
  • @MrLeeh - 好的,你能帮我写代码吗?
  • 您是否有不想使用pandas 的特定原因?我用pandas 写了一个答案,但在看到你的P.S. 后将其删除:)
  • @zipa - 实际上我已经为此使用了 Pandas,但是当我使用 PytQ5 制作和 .exe 应用程序时,它变得像大约 500MB 一样巨大,这主要是因为 Pandas 和 Numpy。 - 这是我使用 Pandas 的代码link

标签: python python-3.x csv


【解决方案1】:

您不能为每个读取行写一行,因为一个输出行可以由多个输入行组成。但是,如果您可以假设输入文件是按照 COUNTRY、EXCHANGE_CODE 和 TOWN 排序的,那么如果 COUNTRY、EXCHANGE_CODE 和 TOWN 相同,则只需在上一行的末尾添加新月份即可。

你的代码可能变成:

...
with open(in_path, 'r') as f_in, open(out_path, 'w', newline='') as f_out:
    csv_reader = csv.reader(f_in, delimiter=';')
    writer = csv.writer(f_out)

    all = []
    row = next(csv_reader)
    row.append('LFU')
    row.append('EXCHANGE_CODE')
    row.append('TOWN_CODE')
    row.append('MONTH_CODE')

    old = row                       # just remember it

    for row in csv_reader:
        if row[0] in ['FRANCE', 'SWEDEN']:

            row.append(row[3].split('%')[0])
            row.append(row[3].split('%')[1])
            row.append(row[3].split('%')[2])
            row.append(row[3].split('%')[3])
            if row[0] == old[0] and row[5] == old[5] and row[6] == old[6]:
                old[7] += ';' + row[7]
            else:
                all.append(old)                      # write down previous row
                old = row
    all.append(old)                                  # do not forget last row

    writer.writerows(map(itemgetter(0, 5, 6, 7), all))

【讨论】:

  • 谢谢你,Serge,这就是我想破脑袋的原因。
【解决方案2】:

如果你想省略所有的库,这里有一个没有导入的解决方案:

with open('smntg.csv') as fin, open('smntg_else.csv', 'w') as fout:
    header = ['COUNTRY', 'EXCHANGE_CODE', 'TOWN_CODE', 'MONTH_CODE']
    data = fin.readlines()
    needed = list(map(str.strip, data))[1:]   
    dealtWith = []
    for line in needed:
        apart = line.split(';')
        country = apart[0]
        exchange, town, month = apart[-1].split('%')[1:]
        dealtWith.append([country, exchange, town, month])        
    packed = {tuple(dealtWith[0][:3]): [dealtWith[0][3]]}
    for item in dealtWith[1:]:
        key = tuple(item[:3])
        value = item[3]
        if key in packed:
            packed[key].append(value)
        else:
            packed[key] = [value]
    joined = {k: ';'.join(v) for k, v in packed.items()}
    finalized = [list(i) + [j] for i, j in joined.items()]
    finalized.sort()
    commaDelimited = [','.join(fline) + '\n' for fline in finalized]
    fout.write(','.join(header) + '\n')
    fout.writelines(commaDelimited)

【讨论】:

  • 感谢您提供的代码,到目前为止,我正试图了解它是如何工作的。(对于像我这样的新手来说看起来有点复杂:p)
猜你喜欢
  • 2021-03-31
  • 2016-10-07
  • 2016-12-15
  • 1970-01-01
  • 2019-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多