0

複数のセンサーからの測定値を含む複数の 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) ごとに 1 つの 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

データ構造がソートに適しているかどうかはわかりません。また、列名を繰り返すようになりました。

4

2 に答える 2

2

私の理解が正しければ、複数のファイルがあり、それぞれが特定の「センサー」に対応し、ファイル名にセンサーの ID が含まれています。ファイルを読み取ってから、別のファイルに書き出す必要があります。今回は「ソース」で分割し、さまざまなセンサーからのデータをいくつかの最終行に結合します。

あなたがやりたいと思うことは次のとおりです。

  1. 次のように、データを読み取り、ネストされたディクショナリ データ構造を構築します。
  2. 最上位のキーはソースになります (例: 'a')。
  3. (date, time)2 番目のレベルは、タプルによってキー設定されます。
  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 月の日付より前に表示されます)。YYYY-MM-DD将来的には、文字列として安全にソートできるISO 8601 スタイルの日付形式を使用することを検討してください。残りの値は解釈なしの文字列としてのみ処理されます。

sensorこのコードは、値を辞書順に並べることができることを前提としています。s1これは、と など、それらの数が少ない場合に発生する可能性がありs2ます。ただし、 がある場合はs10より前にソートされs2ます。これを解決するには、「自然な」並べ替えが必要になります。これは、ここで解決できるよりも複雑です (ただし、詳細については、この最近の質問を参照してください)。

最後に 1 つの警告: このソリューションを同じフォルダーで複数回実行すると、問題が発生する可能性があります。これは、たとえば、出力ファイルが再実行時に入力ファイルとしてa.csv認識されるためです。glob.glob('*.csv')

于 2013-10-29T00:41:38.690 に答える