6
6

More than 1 year has passed since last update.

Pythonを使ったテーブルデータの集計作業メモ

Last updated at Posted at 2020-06-27

テーブルデータに対する、Pythonを使った基本的な作業のメモを書いていきます。


以下の様な何の変哲もないsample_result.csvというCSVファイルに対し、基本的な集計・可視化作業を行っていきます。

image.png


#ライブラリをインポート。
import pandas as pd
import matplotlib.pyplot as plt
import os
#CSVファイルを読み込み。
df = pd.read_csv('data/sample_result.csv')
#エンコーディングスタイルを指定する時はdf = pd.read_csv('data/sample_result.csv', encoding="SHIFT-JISx0213")の様に書く。
display(df)

image.png

元のcsvファイルのクラス名が001などになっている場合は、0落ち防止のため以下の様に書きます。

df = pd.read_csv('data/sample_result.csv',dtype= {'クラス':str})
display(df)

image.png

今回の場合はたった5列しかありませんが、大抵表示しきれないくらい沢山の列がありますのでどんな列があるのかチェックしておきます。

#列名チェック
df.columns

image.png
これでも全部の列名が表示されない時は以下の様に書きます。

list(df.head(0))

image.png

#読み込んだファイル名を表示
name = os.path.basename('data/sample_result.csv')
print(name)

これは特に意味のない作業の様に見えますが、新しくcsvファイルを作成する時、その名前をつける際にこのnameを元にすることもあります。

x = df['受験者']
y = df['数学']
print("数学の平均点は"+str(round(sum(y))/len(y))+"です。")

このコードを実行すると、下の様な文章が表示されます。

image.png

元のcsvファイルにある列をindexとして使う時は以下の様に書きます。

df = pd.read_csv('data/sample_result.csv', index_col='受験者')
display(df)

image.png

数学の点数の一部だけを取り出し、再びテーブルにしてみます。

math_scores = np.array(df['数学'])[:3]
math_scores_df = pd.DataFrame({'数学の点数':math_scores},
                             index = pd.Index(['A','B','C'],
                                             name = '受験者'))
math_scores_df

image.png

標準化や偏差値を求めてみましょう。

#標準化
Z = (math_scores - np.mean(math_scores))/np.std(math_scores)
Z

image.png

#偏差値
Deviation_value = 50 + 10 * Z
Deviation_value

image.png

基本的な可視化

さて、次に棒グラフを描いて見ましょう。

plt.bar(x,y)

image.png

そうすると、皆さんご存知の通り(?)文字化けします。
そこで以下の様なコードを使います。

!pip install japanize-matplotlib
import japanize_matplotlib

※自分の場合はこの方法で上手くいきましたが、他の方法もネットで検索すると色々出てきます。

これで先ほどのコードをもう一度実行すると、今度はきちんと文字が現れました。

image.png

タイトルや軸名を加えて、図のサイズも変えてみましょう。

plt.figure(figsize=(15,6))
plt.bar(x,y)
plt.title("数学の成績")
plt.xlabel("受験者")
plt.ylabel("点数")

image.png

ヒストグラムも描いてみましょう。

plt.hist(df["英語"])

image.png

散布図も描いてみましょう。

z = df['英語']
plt.scatter(y,z)

image.png

グリッドを表示してみましょう。

z = df['英語']
plt.grid(True)
plt.scatter(y,z)

image.png

回帰直線を描いてみましょう。

import numpy as np

y = df['数学']
z = df['英語']

poly_fit=np.polyfit(y,z,1)
poly_1d=np.poly1d(poly_fit)

plt.scatter(y,z)
plt.plot(y,poly_1d(y))

#ついでに画像ファイルを保存。
plt.savefig("test.png")
plt.show()

image.png

因みに以下の様に書くと背景が黒くなります。

z = df['英語']
#先に書かないとダメ。
plt.style.use("dark_background")
plt.scatter(y,z)

image.png

plt.xkcd()を使えば手書き風の味のあるグラフになりますが、元に戻すのが凄い大変なようなのでおススメはしません。

z = df['英語']
plt.xkcd()
plt.scatter(y,z)

image.png

重回帰分析

いきなり話がちょっと高度になりますが、以下の様に書けばお手軽に重回帰分析が出来ます。

import statsmodels.formula.api as smf
formula = '国語 ~ 英語 + 数学'
result = smf.ols(formula, df).fit()
result.summary()

文字型を指定したいとき

例えば実数型にしたい時は以下の様に書きます。

X=df['英語']
X=X.astype('float')
X

image.png

整数を実数に直す時より、どう見ても数なのにPythonが文字だと言い張る時によくこのコードを使います。

データの抽出や整理

特定の列だけ取り出すには、以下の様に書きます。

A = df.loc[:,['受験者','英語']]
display(A)

image.png

ここでちょっと保存してみましょう。最初の方で読み込んでおいたファイル名のnameを使います。

name_split = name.split(".")
name_1 = name_split[0]
A.to_csv('data/'+name_1+'_A.csv', encoding="SHIFT-JISx0213", index=False)

image.png

特定の行だけ取り出すのは以下の様になります。

P = df.loc[[1,3],:]
display(P)

image.png

ある行からある行までをまとめて取り出すには以下の様にします。

display(df[2:5])

image.png

次は国語の成績順に並び替えてみましょう。

#B=を忘れずに。
B = df.sort_values(['国語'],ascending=[False])
display(B)

image.png

「1組で、国語が70点より上」のデータを取り出す場合は以下の様になります。

C = df.query('クラス == ["1組"] & 国語 > 70')
display(C)
#あくまで同じテーブル内の情報しか使えません。他のテーブル内のカラム名をクエリ内に書いてもダメ。

image.png

以下の様に書くこともできます。

C=df[(df['クラス']=='1組')&(df['国語']>70)]
display(C)

配列の結合

以下の様なsample2.csvというファイルの列を結合させてみましょう。

image.png

#CSVファイルを読み込み。
df2 = pd.read_csv('data/sample2.csv',encoding="SHIFT-JISx0213")
#display(df2)
#デフォルトはhow='inner'。
X = pd.merge(df,df2, left_on=df['受験者'], right_on=df2['受験者名'],how="left")
X=X.drop(columns=['受験者名'])
X

image.png

次は以下の様なsample_result_2.csvというテーブルの情報を追加しましょう。

image.png

#CSVファイルを読み込み。
df2 = pd.read_csv('data/sample_result_2.csv')
df.append(df2)

image.png


カテゴリ変数の変換は以下の様に書きます。

X = pd.merge(df,pd.get_dummies(df['クラス']), on=df['受験者'], how="inner")
X = X.drop(columns=['クラス'])
X

image.png

クラスごとの平均点を見るには以下の様に書きます。このテーブルをcsvファイルで出力する時にindex=Falseとしてしまうとクラスの列が消えてしまいます。

df.groupby('クラス').mean()

image.png

小数点以下の桁数を制限するには以下の様に書きます。

pd.set_option('precision',3)

教科ごとの相関係数を見てみましょう。

import seaborn as sns
#cmap ='coolwarm'などもアリ。
sns.heatmap(df.corr(), cmap='Blues',annot = True)

image.png

seabornを使えばいっぺんに全部の組み合わせの散布図も描けます。

sns.pairplot(df)
plt.show()

image.png

全体の基本的な統計量を表示してみましょう。

df.describe()
#引数を指定することも可能。

image.png

意外とあまり本に載っていませんが、空欄の列を作るには以下の様に書きます。

df['合計'] = ''
display(df)

#T = df['合計'] = '',print(T)と書いてもダメ。

image.png

ついでに合計点の計算。

#合計点の計算
i = 0
while i < len(df):
    df['合計'][i] = df['国語'][i] + df['英語'][i] + df['数学'][i]
    i = i + 1
df

image.png

と思ったら以下の様な単純なコードで大丈夫でした。

df['合計'] = df['国語'] + df['英語'] + df['数学']
df

列名の変更は以下の様に書きます。

df = df.rename(columns={'合計':'合計点'})
df

image.png

複数のcsvファイルをまとめて処理するとき

以下の様にglobを使えばOKです。

#ライブラリをインポート。
import pandas as pd
import matplotlib.pyplot as plt
import os
import glob

#dataというフォルダ内にsample_result_1というcsvファイルとsample_result_2というcsvファイルがあるとする。
for doc in glob.glob('test/sample_result_*.csv'):

    #CSVファイルを読み込み。
    df = pd.read_csv(doc)
    display(df)

    #列名チェック
    print(df.columns)

    #読み込んだファイル名を表示
    name = os.path.basename(doc)
    print(name)

    x = df['受験者']
    y = df['数学']

    print("数学の平均点は"+str(round(sum(y))/len(y))+"です。")

欠損値があるとき

下のテーブルをdfとします。

image.png

欠損値を含む行全てを削除するとき。

#ドロップエヌエーと読む。
X = df.dropna()
X

image.png

特定の列に欠損値を含む行を削除するとき。

X = df.dropna(subset=['国語'])
X

image.png

ただしこのような操作を行うと、見てわかる通りindexもそれに合わせて欠けてしまい、例えばこの後にX['国語'][1]などと入力してもエラーになってしまいます。ですので、以下の様にindexを振り直します。

X=X.reset_index()

特定の列に欠損値を含む行だけ抽出するとき。

X=df[df['英語'].isnull()]
X

image.png

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6