ダミーファイル作成プログラムをアップデートしてみる〜Pandasを使ってプログラムを短縮〜

目次

ダミーデータ作成プログラム

前に機械学習を学ぶためにダミーデータ作成プログラムを作ってみました。

その後色々とPythonを勉強してきたので、その成果の一つとして、ダミーデータ作成プログラムを書き直してみようと思います。

これでどれだけ成長したか分かる…かもしれません。

それではプログラムをセッティング部とメインプログラム部に分けて比較していきましょう。

セッティング部

セッティング部に関しては、同じような情報が必要となるため正直それほど大きく変わりません。

前のプログラムのセッティング部はこちら。

import csv
import random
import numpy as np

#Settings

file_name_head = "testdata_"
file_name_end = ""
file_ext = ".txt"

data_name_head = "data_"
data_name_end = ""

value_name_head = "value_"
value_name_end = ""

target_name = "target"

index_name = "dataname"

no_files = 1
rows = 10
columns = 5

target_val = [0, 1]

random_range = [0, 99]
nan_val = range(100, 101)

新しいプログラムのセッティング部はこちら。

import pandas as pd
import random
import numpy as np

#Settings

file_name_head = "testdata_"
file_name_end = ""
file_ext = ".csv"

column_name_head = "value_"
column_name_end = ""

index_name_head = "data_"
index_name_end = ""

target_name = "target"

no_files = 3
no_indexes = 10
no_columns = 5

target_val = [0, 1]
random_range = range(0, 100)
nan_val = range(100, 101)

インポートしているモジュールが「csv」から「pandas」に変わっていることと、列に関するものはcolumnに、行に関係するものはindexに統一しました。

これでプログラムが少し読みやすくなったと思います。

メインプログラム部

大きく変更があったのは、メインプログラム部です。

元々のプログラムはこちら。

#Main

for no_file in range(no_files):
    filename = file_name_head + str(no_file + 1) + file_name_end + file_ext
#     print(filename)
    f = open(filename, "w")
    writer = csv.writer(f)
    
    header = [index_name]
    for column in range(columns):
        valuename = value_name_head + str(column + 1) + value_name_end
        header.append(valuename)
        
    if len(target_val) > 1:
        header.append(target_name)
        
    writer.writerow(header)
    
    for row in range(rows):
        data = []
        dataname = data_name_head + str(row + 1) + data_name_end
        data.append(dataname)
        
        for column in range(columns):
            random_val = random.randint(random_range[0], random_range[1])
            if random_val in nan_val:
                random_val = np.nan
                
            print(random_val)
            data.append(random_val)
                
        if len(target_val) > 1:
            data.append(random.choice(target_val))
                
        writer.writerow(data)
    
    f.close()
    
print("Done")

新しいプログラムのメインプログラム部がこちら。

#Main

for no_file in range(no_files):
    filename = file_name_head + str(no_file + 1) + file_name_end + file_ext
#     print(filename)
    column_name_list = [column_name_head + str(i + 1) + column_name_end for i in range(no_columns)]
#     print(column_name_list)
    index_name_list = [index_name_head + str(i + 1) + index_name_end for i in range(no_indexes)]
#     print(index_name_list)
    df = pd.DataFrame(index=index_name_list, columns=column_name_list)
#     print(df)
    for column in column_name_list:
        df[column] = random.choices(random_range, k=no_indexes)
#     print(df)
    for i in nan_val:
        df = df.replace(i, np.nan)
    
    df[target_name] = random.choices(target_val, k=no_indexes)
    
    df.to_csv(filename)

驚くほど短くなりました。

しかも半分弱は確認のためのprint文だったりします。

元々はfor関数を使ってインデックス名やカラム名を作りつつ、ランダムな値を一つずつ取得し、csvファイルに書き出すということをしていました。

新しいプログラムではどのように処理をしているのか解説していきましょう。

新しいプログラムの解説

まず最初の3行はファイルに関してです。

for no_file in range(no_files):
    filename = file_name_head + str(no_file + 1) + file_name_end + file_ext
#     print(filename)

このプログラムでは複数のダミーデータを出力できるようになっていて、for関数を使って作成するファイル数分プログラムが繰り返されます。

そして2行目でファイル名を作成しています。

3行目は確認のためのファイル名出力です(コメントアウトしています)。

次の4行は列名(カラム名)、行名(インデックス名)の作成です。

    column_name_list = [column_name_head + str(i + 1) + column_name_end for i in range(no_columns)]
#     print(column_name_list)
    index_name_list = [index_name_head + str(i + 1) + index_name_end for i in range(no_indexes)]
#     print(index_name_list)

といっても2行目と4行目は確認のための出力です。

1行目と3行目はリスト内包表記を使って、一度に列名、行名のリストを作成しています。

次に空のデータフレームを作成しています。

    df = pd.DataFrame(index=index_name_list, columns=column_name_list)
#     print(df)

「index=index_name_list」、「columns=column_name_list」とすることで先ほど作成した列名、行名をもつ空のデータフレームが作成しています。

次はそれぞれの列名(カラム名)をfor関数で一つずつ取得し、その列に対して一度にランダムな値を挿入しています。

    for column in column_name_list:
        df[column] = random.choices(random_range, k=no_indexes)

重複ありで複数のランダムな値を取得する「random.choices(リスト, k=取得数)」を使うことでわざわざ一つずつ取得する必要がなくなりました。

次にnanを挿入する処理です。

    for i in nan_val:
        df = df.replace(i, np.nan)

nan_valがセッティング部で「nan_val = range(100, 101)」としてあり、リストとして取得できるため、それぞれの値をfor関数で一つずつ取得し、「df.replace(置換前の値, 置換後の値)」とすることでデータフレーム内の値を一度に変換しています。

そして先ほどと同じようにrandom.choicesを使って、ターゲットの列を作成しています。

    df[target_name] = random.choices(target_val, k=no_indexes)

最後に「.to_csv(出力ファイル名)」で出力しています。

df.to_csv(filename)

これだけ短くなったら分かりにくいのかなと思ったのですが、むしろ前の長いプログラムの方が分かりにくく、新しい方が一つ一つの処理が理解しやすいのではないかと思います。

ただそれもそれぞれの関数が何をやっているかとかリスト内包表記の知識があった上のこと。

自分でプログラムを書いていくというのも大切なのですが、今回の件は新しい知識を学ぶことが大事だと分かる比較だったのではないかと思います。

ということでどんどんと新しい知識を仕入れていきましょう。

ちなみにGitHubにもアップロードしてありますので、良かったらこちらもどうぞ。

ではでは今回はこんな感じで。

よかったらシェアしてね!

コメント

コメントする

目次
閉じる