【问题标题】:Create a duplicate row in csv file to separate multiple values in a column (python)在 csv 文件中创建重复行以分隔列中的多个值(python)
【发布时间】:2017-04-26 07:35:27
【问题描述】:

我正在尝试在 Python 中构建一些代码以将列中的多个值分成单独的行,并根据时间戳的同一天聚合 Active-Ticket 的列,是否可以使用任何内部库或者我可以使用需要安装外部库吗?

我的示例文件是(目前,Active-Tickets 列是空的):

Input.csv

Timestamp,CaseID,Active-Tickets   
14FEB2017:10:55:23,K456 G578 T213,        
13FEB2017:10:56:12,F891 A63,
14FEB2017:11:59:14,T427 T31212 F900000,
15FEB2017:03:55:23,K456 G578 T213,        
14FEB2017:05:56:12,F891 A63,

我想要达到的目标:

输出.csv

Timestamp,CaseID,Active-Tickets
14FEB2017:10:55:23,K456,8 (because there are 8 cases happened on the same day)
14FEB2017:10:55:23,G578,8
14FEB2017:10:55:23,T213,8        
13FEB2017:10:56:12,F891,2 (because there are 2 cases happened on the same day)
13FEB2017:10:56:12,A63,2
14FEB2017:11:59:14,T427,8
14FEB2017:11:59:14,T31212,8
14FEB2017:11:59:14,F900000,8
15FEB2017:03:55:23,K456,3 (because there are 3 cases happened on the same day)
15FEB2017:03:55:23,G578,3
15FEB2017:03:55:23,T213,3        
14FEB2017:05:56:12,F891,8
14FEB2017:05:56:12,A63,8

我的想法是:

  1. 获取时间戳列的值

  2. 检查日期是否相同,

  3. 将所有以空格分隔的 CaseID 存储到基于日期的列表中,

  4. 然后计算每个日期列表中元素的数量

  5. 将计数元素的值返回到Active-Tickets。

但是这里的问题是,数据量不小,假设一天最少有50个案例,那我觉得我的方法不太可能。

【问题讨论】:

  • 我将使用由日期字段索引的哈希值,其中值将是由具有数字作为值的 CaseID 索引的哈希值。使用 defaultdict 实现应该非常简单,只要它可以放入内存。如果您的数据非常庞大,您可以查看shelve 或sqlite3 模块。但是这个问题目前相当广泛......
  • @SergeBallesta 谢谢。我会看看这些模块。每个文件的数据大约 2gb,所以我只能测试包含数千个数据的样本。当您说 sqlite3 模块时,这是否意味着我需要为 csv 文件创建一个数据库?
  • 取决于输入文件是否按日期/时间戳排序。如果是这样,您只需要在内存中保留一天,所以只需忘记搁置或 sqlite3。如果订单是纯随机的,您可以首先使用外部排序程序回退到第一个用例,或者直接使用数据库存储在磁盘上,所以是的,您可以将 csv 文件的相关部分存储到 sqlites3 数据库中并使用查询GROUP BY dat, caseid.

标签: python csv python-2.6


【解决方案1】:

这是使用itertools.chain.from_iterable() 的一种方法。它仅将计数保存在内存中,因此可能适用于您的情况。它两次读取csv 文件。一次获取计数,一次写入输出,但仅使用迭代器进行读取,因此应减少内存需求。

代码:

import csv
import itertools as it
from collections import Counter

# read through file and get counts per date
with open('test.csv', 'rU') as f:
    reader = csv.reader(f)
    header = next(reader)
    dates = it.chain.from_iterable(
        [date for _ in ids.split()]
        for date, ids in ((x[0].split(':')[0], x[1]) for x in reader))
    counts = Counter(dates)

# read through file again, and output as individual records with counts
with open('test.csv', 'rU') as f:
    reader = csv.reader(f)
    header = next(reader)
    records = it.chain.from_iterable(
        [(l[0], d) for d in l[1].split()] for l in reader)
    new_lines = (l + (str(counts[l[0].split(':')[0]]), ) for l in records)

    with open('test2.csv', 'wb') as f_out:
        writer = csv.writer(f_out)
        writer.writerow(header)
        writer.writerows(new_lines)

结果:

Timestamp,CaseID,Active-Tickets
14FEB2017:10:55:23,K456,8
14FEB2017:10:55:23,G578,8
14FEB2017:10:55:23,T213,8
13FEB2017:10:56:12,F891,2
13FEB2017:10:56:12,A63,2
14FEB2017:11:59:14,T427,8
14FEB2017:11:59:14,T31212,8
14FEB2017:11:59:14,F900000,8
15FEB2017:03:55:23,K456,3
15FEB2017:03:55:23,G578,3
15FEB2017:03:55:23,T213,3
14FEB2017:05:56:12,F891,8
14FEB2017:05:56:12,A63,8

2.6 中的计数器

collections.Counter 已被向后移植到 python 2.5+ (Here)

【讨论】:

  • 嗨,我收到以下错误。 _csv.Error: line contains NULL byte。这是否意味着我的 CaseID 不能包含 0 数据?那么,我应该先删除 CaseID 列中包含空数据的行,然后在运行此代码之前在 CaseID 中输出一个包含非 NULL 数据的新 csv 文件?或者这不是困扰我的原因?
猜你喜欢
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
  • 2018-10-26
  • 2023-03-31
  • 2021-09-17
  • 2021-06-21
  • 1970-01-01
相关资源
最近更新 更多