繁体   English   中英

拆分,合并,排序CSV

[英]Splitting, merging, sorting CSV

我有几个CSV文件,其中包含来自多个传感器的测量值

s1.CSV:

date;hour;source;values
01/25/12;10:20:00;a; 88 -84 27
01/25/12;10:30:00;a; -80
01/25/12;10:50:00;b; -96 3 -88
01/25/12;09:00:00;b; -97 101
01/25/12;09:10:00;c; 28

s2.CSV:

date;hour;source;values
01/25/12;10:20:00;a; 133
01/25/12;10:25:00;a; -8 -5

我想按来源(a / b / c)创建一个CSV文件,并将每列中的每个度量按日期和小时排序

a.CSV:

date;hour;source;s1;s2
01/25/12;10:20:00;a; 88 -84 27; 133
01/25/12;10:25:00;a; ; -8 -5
01/25/12;10:30:00;a; -80;

...

我被困在这里:

import glob
import csv
import os
os.system('cls')

sources = dict()
sensor = 0

filelist = glob.glob("*.csv")

for f in filelist:
    reader = csv.DictReader(open(f),delimiter=";")
    for row in reader:
#       date = row['date'] # date later
        hour = row['hour']
        val = row['values']
        source = row['source']

        if not sources.has_key(source): # new source
            sources[source] = list()
#       
        sources[source].append({'hour':hour, 'sensor'+`sensor`:val})

    sensor+=1

我不确定数据结构是否可以排序。 我也喜欢重复列名。

使用您提供的数据,我使用Pandas制作了东西。 请参见下面的代码。

授予的输出是不理想的,因为hoursource在列中重复出现。 在学习的同时,我也欢迎任何专家提供有关Pandas是否可以执行OP要求的信息!

In [1]: import pandas as pd

In [2]: s1 = pd.read_csv('s1.csv', delimiter=';', parse_dates=True)

In [3]: s1
Out[3]: 
       date      hour source      values
0  01/25/12  10:20:00      a   88 -84 27
1  01/25/12  10:30:00      a         -80
2  01/25/12  10:50:00      b   -96 3 -88
3  01/25/12  09:00:00      b     -97 101
4  01/25/12  09:10:00      c          28

In [4]: s2 = pd.read_csv('s2.csv', delimiter=';', parse_dates=True)

In [5]: s2
Out[5]: 
       date      hour source  values
0  01/25/12  10:20:00      a     133
1  01/25/12  10:25:00      a   -8 -5

In [6]: joined = s1.append(s2)

In [7]: joined
Out[7]: 
       date      hour source      values
0  01/25/12  10:20:00      a   88 -84 27
1  01/25/12  10:30:00      a         -80
2  01/25/12  10:50:00      b   -96 3 -88
3  01/25/12  09:00:00      b     -97 101
4  01/25/12  09:10:00      c          28
0  01/25/12  10:20:00      a         133
1  01/25/12  10:25:00      a       -8 -5

In [8]: grouped = joined.groupby('hour').sum() 

In [9]: grouped.to_csv('a.csv')

In [10]: grouped
Out[10]: 
                      date source          values
hour                                             
09:00:00          01/25/12      b         -97 101
09:10:00          01/25/12      c              28
10:20:00  01/25/1201/25/12     aa   88 -84 27 133
10:25:00          01/25/12      a           -8 -5
10:30:00          01/25/12      a             -80
10:50:00          01/25/12      b       -96 3 -88

如果我理解正确,则您有多个文件,每个文件对应一个给定的“传感器”,文件名中包含传感器的标识。 您想要读取文件,然后将它们再次写出为单独的文件,这次用“源”进行划分,并将来自不同传感器的数据合并为最后几行。

这是我想您要执行的操作:

  1. 读入数据,并构建一个嵌套的字典数据结构,如下所示:
  2. 顶级密钥将是源(例如'a' )。
  3. 第二级将由(date, time)元组作为键。
  4. 最里面的级别将由传感器(从文件名中获取)进行键控,并将传感器的实际读数作为值。
  5. 您还希望跟踪所见过的所有传感器。
  6. 要写出数据,您需要遍历最外面的字典的项目,为每个字典创建一个新的输出文件。
  7. 每个文件的行将通过对下一个字典的键进行排序来确定。
  8. 每行的最后一个值将通过串联最里面的dict的值来形成,并为任何缺少的值填充一个空字符串。

这是一些代码:

from collections import defaultdict
from datetime import datetime
import csv
import glob
import os

# data structure is data[source][date, time][sensor] = value, with "" as default value
data = defaultdict(lambda: defaultdict(lambda: defaultdict(str)))
sensors = []

filelist = glob.glob("*.csv")

# read old files
for fn in filelist:
    sensor = os.path.splitext(fn)[0]
    sensors.append(sensor)
    with open(fn, 'rb') as f:
        reader = csv.DictReader(f, delimiter=";")
        for row in reader:
            date = datetime.strptime(row['date'], '%m/%d/%y')
            data[row['source']][date, row['hour']][sensor] = row['values']

sensors.sort() # note, this may not give the best sort order
header = ['date', 'hour', 'source'] + sensors

for source, source_data in data.iteritems():
    fn = "{}.csv".format(source)
    with open(fn, 'wb') as f:
        writer = csv.writer(f, delimiter=";")
        writer.writerow(header)
        for (date, time), hour_data in sorted(source_data.items()):
            values = [hour_data[sensor] for sensor in sensors]
            writer.writerow([date.strftime('%m/%d/%y'), time, source] + values)

我只会将日期字段转换为内部类型,因为否则基于日期的排序将无法正常进行(2013年1月的日期会比2012年2月的日期早)。 将来,请考虑使用ISO 8601样式的日期格式YYYY-MM-DD ,可以将其安全地排序为字符串。 其余值仅作为没有解释的字符串处理。

该代码假定可以按字典顺序对sensor值进行排序。 如果只有几个,例如s1s2 ,则可能会出现这种情况。 但是,如果您有s10 ,它将在s2之前排序。 为了解决这个问题,您需要一个“自然”排序,这种排序比我在这里可以解决的复杂(但请参阅此最新问题以获取更多信息)。

最后一条警告:如果您在同一文件夹中运行多个时间,此解决方案可能会做坏事。 这是因为当您再次运行时, glob.glob('*.csv')会将输出文件(例如a.csv glob.glob('*.csv')视为输入文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM