上流SEが久しぶりに開発してみる日記

マネジメント専任システムエンジニアがなれないプログラミングをしてみる日記です。

python データフレームでのクロス集計(2項目間の組み合わせの数・値の偏りを確認)するcrosstab関数

データフレームでのクロス集計(2項目間の組み合わせの数)する、 crosstab関数の使い方です。

import pandas as pd
import numpy as np


#データを作る
data = [["A0",1],["A1",0],["A0",0],["A0",1]]
df = pd.DataFrame(data=data, columns=['A','B'])
df
A B
0 A0 1
1 A1 0
2 A0 0
3 A0 1
pd.crosstab(df["A"],df["B"],margins=True)
B 0 1 All
A
A0 1 2 3
A1 1 0 1
All 2 2 4

項目Aの値それぞれに対して1,0のどちらを取ったのか件数が出力されます。 取りうる値がどこにどれだけの偏りがあるのかを確認するのに便利な関数です。

python 基礎 データフレームからの抽出~応用編~

データフレームからのデータ抽出の応用編です。

データフレームからのデータ抽出の応用編です。 まずは、2つのデータフレームを用いた抽出です。

2つのデータフレームで特定のキーが同じものだけを抽出します。

import pandas as pd
import numpy as np


#データフレームから必要なデータを抽出する方法を整理します。

#データを作る
data = [["A0","B0","C0",0],["A1","B1","C1",1],["A2","B2","C2",2]]
df1 = pd.DataFrame(data=data, columns=['A','B','C','D'])
print("df1")
print(df1)

data2 = [["A2","E2","F2",10],["A3","E3","F3",20],["A4","E4","F4",30]]
df2 = pd.DataFrame(data=data2, columns=['A','E','F','G'])
print("df2")
print(df2)
df1
    A   B   C  D
0  A0  B0  C0  0
1  A1  B1  C1  1
2  A2  B2  C2  2
df2
    A   E   F   G
0  A2  E2  F2  10
1  A3  E3  F3  20
2  A4  E4  F4  30

df2と同じAのキーをもつdf1を抽出 ここではAをキーとします。

df1[df1['A'].isin(df2['A'])]
A B C D
2 A2 B2 C2 2

df2と同じAのキーを持たないdf1を抽出 ここでもAをキーとします。(差分抽出)

df1[~df1['A'].isin(df2['A'])]
A B C D
0 A0 B0 C0 0
1 A1 B1 C1 1

特定の文字列(複数)を含むデータを抽出 ここでは、df1のA列に1を含む/含まないデータの抽出

print("対象を含むデータの抽出")
print(df1[df1['A'].str.contains('1')])

print("対象を含まないデータの抽出")
print(df1[~df1['A'].str.contains('1')])
対象を含むデータの抽出
    A   B   C  D
1  A1  B1  C1  1
対象を含まないデータの抽出
    A   B   C  D
0  A0  B0  C0  0
2  A2  B2  C2  2

特定の文字列(複数)を含むデータを抽出 ここでは、df1のA列に0または1を含む/含まないデータの抽出

#検索したい文字列のリスト
stringlist = ["0","1"]

indexlist = []

#検索したい文字列を1件ずつループ。含まれていた場合のインデックスをリストに追加していく。
for i in range(len(stringlist)):
    indexlist.extend(df1.index[df1['A'].str.contains(stringlist[i])].tolist())

#出力したリストをそのまま使うと重複あるので、重複排除して、ソート。
#unique使うと勝手にソートされてしまうが、今回は好都合。
label_list = np.unique(indexlist).tolist()

print("対象を含むデータの抽出")
print(df1.reindex(index=label_list))

print("対象を含まないデータの抽出")
print(df1.drop(index=label_list))
対象を含むデータの抽出
    A   B   C  D
0  A0  B0  C0  0
1  A1  B1  C1  1
対象を含まないデータの抽出
    A   B   C  D
2  A2  B2  C2  2

python 基礎 データフレームの抽出

データフレームの抽出方法を整理します。

本当の基礎編です。

###python の基礎② データフレーム抽出
import pandas as pd
import numpy as np


#データフレームから必要なデータを抽出する方法を整理します。

#データを作る
data = [["A0","B0","C0",0],["A1","B1","C1",1],["A2","B2","C2",2]]
df = pd.DataFrame(data=data, columns=['A','B','C','D'])
print(df)
    A   B   C  D
0  A0  B0  C0  0
1  A1  B1  C1  1
2  A2  B2  C2  2

特定の列を抽出する。(Series) Seriesとはpandasのオブジェクトで1次元のデータを扱うものです。 DataFrameは2次元のデータを扱うもの。 Seriesで抽出するとオブジェクトとして抽出されるため、若干動きが異なる点に注意が必要です。

df['B']
0    B0
1    B1
2    B2
Name: B, dtype: object

特定の列を抽出する。(DataFrame) DataFrameとして列指定で抽出する場合は[]を2重にします。

df[['B']]
B
0 B0
1 B1
2 B2

特定の列2つを抽出する。(DataFrame) 抽出したい列が複数ある場合はカンマで選択できます。

df[['B','C']]
B C
0 B0 C0
1 B1 C1
2 B2 C2

行の抽出 条件を指定して抽出する ==

df[df['B']=="B1"]
A B C D
1 A1 B1 C1 1

行の抽出 条件を指定して抽出する >

df[df['D'] > 0]
A B C D
1 A1 B1 C1 1
2 A2 B2 C2 2

行の抽出 条件に一致しないものは~を使います。

df[~(df['D'] > 0)]
A B C D
0 A0 B0 C0 0

行の抽出 含まれているかどうかの判定はisinを使う 複数指定したい場合はカンマで区切る

df[df['D'].isin([1,2])]
A B C D
1 A1 B1 C1 1
2 A2 B2 C2 2

行列の指定 locは行、列のラベルを指定して抽出する。

df.loc[0,'A']
'A0'

行列の指定 locは1行だけ指定するとseriesになる。

df.loc[0]
A    A0
B    B0
C    C0
D     0
Name: 0, dtype: object

行列の指定 ilocは行、列の番号を指定して抽出する

df.iloc[0,2]
'C0'

行列の指定 ilocは1行だけ指定するとseriesになる。

df.iloc[0]
A    A0
B    B0
C    C0
D     0
Name: 0, dtype: object

行列の指定 :はすべて、列は[]で複数指定可能

df.loc[:,['A','D']]
A D
0 A0 0
1 A1 1
2 A2 2

行列の指定 :はすべて、列は[]で複数指定可能

df.iloc[:,[0,2]]
A C
0 A0 C0
1 A1 C1
2 A2 C2

python 基礎データフレームの作り方

pythonの勉強をしていくと、覚えるのが大変なので、

自分の備忘がてら基礎を整理していこうと思います。

今回はデータフレームの作り方を整理します。

データフレームとはpythonのpandasライブラリに含まれているオブジェクトの事です。

簡単に言うと2次元の表形式でデータを加工できます。

なぜpythonがデータサイエンティストでよく使われているかというと、このデータフレームがあるからなのでは?と思っています。

実際使い勝手がよく、DBを簡単に操作するようにデータを扱うことができるのがメリットです。

あと関数が直感的にわかりやすい!

ということで、今回はそのデータフレームの作り方の基本を整理します。

###python の基礎 データフレームの作り方
import pandas as pd
import numpy as np


#pd.DataFrame()を使って生成する。
#data,columns,indexを指定できる。
#dataはその名の通り設定したいデータを指定する。
#columnsは列名を指定する。
#indexは各行のindex名を指定する。(未指定だとデフォルトで番号が振られる。)

#例①4行1列のデータを作る
data = ["A1","B2","C3","C1"]
df1 = pd.DataFrame(data=data, columns=['label'],index=['A','B','C','D'])
print("df1:4行1列")
print(df1)

#例②1行4列のデータを作る
data = [["A1","B2","C3","C1"]]
df2 = pd.DataFrame(data=data, columns=['A','B','C','D'], index=['row0'])
print("df2:1行4列")
print(df2)

#csvを取り込む
#pd.read_csv関数を使う。
#ファイル名を指定すれば取り込める。
#カラム名やデータに日本語がある場合はshift-jisへ変換するのを忘れにように(文字化けする。)
df_csv = pd.read_csv('input.csv',encoding='shift jis')
print("df_csv:csvから取り込み")
print(df_csv)


#jsonファイルを取り込む
#pd.read_json関数を使う。
#ファイル名を指定すれば取り込める。
#orientでjsonの取り込み形式が決まる。jsonの形式に応じて選択が必要。
#orient='dict':keyが列ラベル、valueが行ラベルと値になる
##{column:{index:value}}
#orient='list':keyが列ラベル、valueが値になる 行名は失われる
##{column:[values}}
#orient='series':keyが列ラベル、valueが行ラベルと値になるpndas.seriesになる。
##{column:series(values)}
#orient='split':keyが'index', 'columns', 'data'で、それぞれの値が行ラベル、列ラベル、値となる。
##{index:[index],colums:[colmuns],data:[values]}
#orient='records':keyが列ラベル、valueが値となるリストとする。行名の情報は失われる。
##{{column:value},・・・,{column:value}}

df_json = pd.read_json('input.json', orient='records')
print("df_json:jsonから取り込み")
print(df_json)
df1:4行1列
  label
A    A1
B    B2
C    C3
D    C1
df2:1行4列
       A   B   C   D
row0  A1  B2  C3  C1
df_csv:csvから取り込み
   A  B
0  1  5
1  2  6
2  3  7
3  4  8
df_json:jsonから取り込み
   A  B
0  1  2
1  3  4

インプットファイルは以下です。

■input.csv

A B
1 5
2 6
3 7
4 8

■input.json

[{"A":1,"B":2},{"A":3,"B":4}]

日々の幸せだと思ったことを記録するWebアプリ構築[python golang GCP]

去年の4月くらいから久しぶりにコーディングしてみて、

1年弱経ちました。

 

ここで作ったものを並べておくと

食べログ評価順ソートツール

・sumoの新着物件自動lineツール

・中古物件の相場算出ツール(機械学習

先物オプション自動売買ツール

・外貨自動送金ツール

・触覚ニュース自動lineツール

・幸せログ記録システム

 

こんな感じです。

まあまあ作れましたね。

 

先物オプション自動売買ツールなんかは作って運用して1か月で50万の損失だしたので、止めましたが。。。

 

そんな失敗も開発していると楽しいもんです。

 

 

今日は最後の幸せログ記録システムってのを紹介します。

 

まず、目的!

 

 

■目的

自分が日々何に幸せを感じているのかを可視化して、今後もっと幸せになる!

 

です。

 

自分でどんなこと幸せに感じているのかをサクッとメモして履歴として残してあとで分析してみようというものです。

 

 

■システム構成

 

f:id:sefather:20220212075945p:plain

幸せログシステム構成

 

お金をかけたくなかったのでGCP上にすべて構築しました。

 

言語は自分が勉強したかったpythonと、簡単そうなgolangを採用。

 

DBはお金かけないようにjsonのファイルで代用。

 

って感じです。

 

GAEの機能で指定したgoogleアカウントでのみしか利用できない認証機能を設定できるので、

外部にさらされることもなく安心して使っています。(個人用として。)

 

■UI

UIはあまりこだわっていませんが、(個人用なので)こんな感じです。

 

f:id:sefather:20220212081039p:plain

ログの登録画面

f:id:sefather:20211121172203p:plain

分析結果

f:id:sefather:20211121172644p:plain

グラフ

 

■開発に関する感想

GCPってすごいですね。

昔はあれだけwebサーバ構築する作業が面倒だったのがこんな簡単にできるとはって感じです。

アプリをスマホに入れれば遠隔地でログモニタリングもできます。

しかもこれぐらいのシステムであれば、個人利用ではありますが、月10円ぐらいで運用できます。

 

コーディングも見知らぬ言語で手間取ったこともありますが、pythonという言語がjavaなんかと比べると分かりやすくていいですね。

極めなくてよければ、かなり初心者にやさしいですね。

 

■その他感想

幸せの記録って結構面白いですね。

最後のグラフなんて、登録した幸せな事柄の言葉を形態素解析して、

単語間の関連をグラフ化してみたものですが、

いろんな事柄が関連づいて自分の幸せというものが形成されているのが、

どれだけ複雑かってことがよくわかります。

 

 

ログをとりはじめて3か月ぐらいですが、分析して分かったことは以下の通りです。

・自分の幸せの50%は家族によってもたらされている。

・自分のやりたいことに熱中しているときは幸せ(先物オプションの自動売買ツールを作っているときはかなり熱中していたので幸福度がかなり上がりました。)

・目に見えた成果がでると幸せ。腰痛防止のために体を柔らかくするように医者に言われていますが、毎日ストレッチした結果、前屈でつま先に届いたときはかなり幸せでした!

 

■今後に向けて

もう少しログを記録して分析してみつつ、

マネフォの支出と紐づけたいですね。

それで、幸せのコスパが高い支出とか分析してみたいです。

 

 

 

python データフレームでgroupbyしたけどキー項目がindexキーになって扱いづらい

前回以下で週次集計が簡単だって感動していました。

 

 

df.groupby(pd.Grouper(key="when", freq="W-MON", closed="left", label="left")).sum()

 

 

でもkey項目(上記だとwhen)がindexになるんで、json出力するときとか扱いづらいので、

普通の項目として扱いたいです。

 

 

df.groupby(pd.Grouper(key="when", freq="W-MON", closed="left", label="left")).sum().reset_index()

 

reset_index()でindexから外れて通常のカラムになりました。

 

python データフレームの日付での週次、月次の集計

週次、月次で集計したいなー

 

#週次で集計
df.groupby(pd.Grouper(key="when", freq="W")).sum()

 

#月次で集計
df.groupby(pd.Grouper(key="when", freq="M")).sum()

 

日付のkeyを指定して(今回はwhen)、freqをW(週次)、M(月次)でしていするだけ。

 

なんて簡単なんだ!

 

pythonはわかりやすさ優先しているだけあるわ。