【Python】IBS-TH1 PLUSのデータ分析:ヘッダーとデータを場合分け

  • URLをコピーしました!
目次

前回のおさらい:CSVファイルの読み込み

前回は温度・湿度ロガーのデータを分析するため、CSVファイルを読み込む部分のプログラムを作成しました。

まずはとりあえず前回のコードを見てみます。

import os
import shutil
import csv

path = os.getcwd()

data_path = path + "//Data//"

for f in os.listdir(path):
    if f[-4:] == ".csv":
        shutil.move(f, data_path + f)
        
for f in os.listdir(data_path):
    if f[-4:] == ".csv":
        file = open(data_path + f, "r")
        reader = csv.reader(file)
        
        for row in reader:
            print(row)

実行結果
['Time', 'Temperature_C', 'Relative_Humidity']
['2019-12-29 18:53:36', '26.59', '22.12']
['2019-12-29 19:23:36', '25.37', '23.46']
['2019-12-29 19:53:36', '24.15', '24.79']
['2019-12-29 20:23:36', '22.93', '26.13']
['2019-12-29 20:53:36', '21.71', '27.46']
['2019-12-29 21:23:36', '20.48', '28.8']
(以下省略)

ここでの問題点はヘッダーとデータが同じように取得されてしまっていることと、日時のデータと温度・湿度のデータが文字(str)となってしまっていることです。

ということで今回はヘッダーとデータの行を分けるプログラムを作成していきます。

それぞれの値を別々に取得

先ほどの実行結果ではprint(row)とすることでデータを一括で表示していました。

そこでまずはそれぞれの値を別々に取得してみます。

rowは現在、リストとなっているので、row[0]とすると最初の値が、row[1]とすると2番目の値、row[2] とすると3番目の値を取得することができます。

import os
import shutil
import csv

path = os.getcwd()

data_path = path + "//Data//"

for f in os.listdir(path):
    if f[-4:] == ".csv":
        shutil.move(f, data_path + f)
        
for f in os.listdir(data_path):
    if f[-4:] == ".csv":
        file = open(data_path + f, "r")
        reader = csv.reader(file)
        
        for row in reader:
            print(row[0], row[1], row[2])

実行結果
Time Temperature_C Relative_Humidity
2019-12-29 18:53:36 26.59 22.12
2019-12-29 19:23:36 25.37 23.46
2019-12-29 19:53:36 24.15 24.79
2019-12-29 20:23:36 22.93 26.13
2019-12-29 20:53:36 21.71 27.46
(以下省略)

ヘッダーの場合分け

先ほどの実行結果をみると最初の行はヘッダー、二行目からデータとなっています。

とりあえずここを場合分けします。

どう場合分けするかというと、最初の行ヘッダーは3つとも文字、二行目以降は日時、小数、小数となっています。(ただし現状では全てstr型)

ということで2つ目、3つ目の値が、str型(文字)から小数であるfloat型に変換できれば、その行はデータの行だと分かります。

逆に変換できなかった場合はヘッダーということです。

ここで使うのは、例外処理であるtry – except文です。

要するにfloat型に変換してみて、出来たなら「True」、できなかったら「False」という値を返す関数を作り、2つ目、3つ目の数値で「True」が返ってくる行を取得するというわけです。

そのfloat型に変換できるか判定する関数はこんな感じです。

def is_float(val):
    try:
        float(val)
    except:
        return False
    else:
        return True

これを先ほどのプログラムに組み込んで、ちゃんと判定ができているか確認します。

import os
import shutil
import csv

def is_float(val):
    try:
        float(val)
    except:
        return False
    else:
        return True

path = os.getcwd()

data_path = path + "//Data//"

for f in os.listdir(path):
    if f[-4:] == ".csv":
        shutil.move(f, data_path + f)
        
for f in os.listdir(data_path):
    if f[-4:] == ".csv":
        file = open(data_path + f, "r")
        reader = csv.reader(file)
        
        for row in reader:
            print(is_float(row[0]), is_float(row[1]),is_float(row[2]))

実行結果
False False False
False True True
False True True
False True True
False True True
False True True
(以下省略)

とりあえず2つ目(row[1])、3つ目(row[2])の値だけでなく、最初の値(row[0])も確認してみました。

最初の行はすべて文字なので「False」、つまりfloat型に変換できないということで予想通りです。

二行目からは最初の値(row[0])は日時のためfloat型に変換できない(False)、しかし2つ目(row[1])、3つ目(row[2])の値はfloat型に変換できる(True)ということでこちらも予想通りです。

ということでこの関数とif文を使って、データの行だけ場合分けします。

import os
import shutil
import csv

def is_float(val):
    try:
        float(val)
    except:
        return False
    else:
        return True

path = os.getcwd()

data_path = path + "//Data//"

for f in os.listdir(path):
    if f[-4:] == ".csv":
        shutil.move(f, data_path + f)
        
for f in os.listdir(data_path):
    if f[-4:] == ".csv":
        file = open(data_path + f, "r")
        reader = csv.reader(file)
        
        for row in reader:
            if row != [] and is_float(row[1]) == True and is_float(row[2]) == True:
                print(row)

出力結果
['2019-12-29 18:53:36', '26.59', '22.12']
['2019-12-29 19:23:36', '25.37', '23.46']
['2019-12-29 19:53:36', '24.15', '24.79']
['2019-12-29 20:23:36', '22.93', '26.13']
['2019-12-29 20:53:36', '21.71', '27.46']
(以下省略)

今回はヘッダー行が表示されませんでした。

ということで正しくデータの行を取得できていることでしょう。

ちなみにif文をちょっと解説しておきましょう。

if row != [] and is_float(row[1]) == True and is_float(row[2]) == True:

最初の row != [] は、その行が空白行でない(!= は notの意味)ことを示しています。

そして is_float(row[1]) == True と is_float(row[2]) == True で2つ目と3つ目の値が小数であることを示しています。

全て「and」で繋がっているので、空白行ではなく、row[1]とrow[2]が小数である場合のみが場合分けされます。

これでデータが取得することができました。

次回はもう一つの問題である「値が全てstr型になっている」に対処していきましょう。

ということで今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次