按多个CSV列压缩排序

2024-10-03 04:36:15 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我使用的csv文件看起来像:

Date Time,            SegmentID,   indicatorvalue
2016-12-01T00:00:00Z  147649       1
2016-12-01T00:01:00Z  147649       0
2016-12-01T00:02:00Z  147649       1
...                   ...          ...
2016-12-01T00:23:00Z  2938733      0

等等。在

我想要的是把它压缩成一个包含所有段的列表,然后根据一天中的时间(AM/IP/PM/OP)显示该段的条目数的百分比

例如:

^{pr2}$

我的尝试是设置一个for循环,这样对于每个段,它将保持一天中4次指示器百分比的运行总数,然后一旦它检测到它已更改为一个新的segmentID,它就会将这些值附加到一个字符串中。在

问题是segmentID是无序的,导致同一segmentID有多个条目。我试着按SegmentID对文件排序,但文件太大了。对另一种方法有什么建议吗?在

编辑: 有人删除了他们的评论,说我应该用熊猫,所以经过一番研究,我的代码是:

import numpy as np
import pandas as pd

df=pd.read_csv("data.csv",sep=",",index_col="Segment ID",usecols=["Segment ID","Date Time","indicatorvalue"])
df['Date Time'] = ['AM' if '06' <= x[11:13] < '10' 
    else 'IP' if '10' <= x[11:13] < '16' 
    else 'PM' if '16' <= x[11:13] < '19'
    else 'OP' if '19' <= x[11:13] or x[11:13] < '06'
    else 'Error' for x in df['Date Time']]

现在我只需要弄清楚如何用“Date Time”和“SegmentID”的重复条目压缩行,同时求它们的“indicatorvalues”的平均值。在


Tags: 文件csvipdfdateiftime条目
2条回答

我设法用熊猫找到了解决办法。我使用的代码是:

import pandas as pd

df=pd.read_csv("data.csv",sep=",",usecols=["Segment ID","Date Time","indicator value"])

df['Date Time'] = ['AM' if '06' <= x[11:13] < '10' 
   else 'IP' if '10' <= x[11:13] < '16' 
   else 'PM' if '16' <= x[11:13] < '19'
   else 'OP' if '19' <= x[11:13] or x[11:13] < '06'
   else 'Error' for x in df['Date Time']]

grouped = df.groupby(['Segment ID','Date Time']).mean() 

grouped.to_csv('output.csv', sep =',')

我再推荐熊猫也不够。在

我假设输入文件的结构是每分钟一行,给出开始时间、段id和指示符的值。在

如果段的数量与可用内存兼容,我只需一次在线读取输入文件,并将分钟数添加到每个段的8个计数器,即每天的时间和指示符值。这意味着初始文件只读取一次,而不是排序,唯一关键的数量是段的数量-如果它变得太高,我将使用sqlite3或dbm数据库而不是dict

对于您当前的示例(使用isnotcsv),代码可以是:

class Segment:
    labels = ['AM', 'IP', 'PM', 'OP']
    def __init__(self, segid):
        self.id = segid
        self.values = [ [ 0, 0 ] for i in range(4) ]
    def add(self, hour, indic):
        ix = 3
        if hour >= 6 and hour < 10: ix=0
        elif hour >= 10 and hour < 16: ix=1
        elif hour >= 16 and hour < 19: ix = 2
        self.values[ix][indic] += 1
    def percent(self, ix):
        try:
            return int(.5 + (100 * self.values[ix][1] /
                 (self.values[ix][0] + self.values[ix][1])))
        except ZeroDivisionError:
            return 0

dummy = next(fd)
splitter = re.compile(' +')
segments = dict()
for line in fd:  # read and store
    d, seg, indic = splitter.split(line.strip())  # could be replaced with a csv reader
    hour = int(d[11:13])
    if not seg in segments:
        segments[seg] = Segment(seg)
    segments[seg].add(hour, int(indic))
for seg in sorted(segments.keys()):  # output the stats
    for ix in range(4):
        print(seg, Segment.labels[ix], segments[seg].percent(ix))

上面的代码缺少对错误或异常情况的测试

相关问题 更多 >