データサイエンス グラフ 日本地図 地図 自然言語処理 Streamlit
データサイエンスとは大量のデータを整理、分析することで、問題の解決策を得ることです。そのために統計などの数学的手法や、機械学習などを用います。
データサイエンスに取り組む人をデータサイエンティストと言います。データサイエンティストに必要な能力は統計学・数学などの知識、プログラミングなどのエンジニア能力、ビジネスの問題を見つけ、解決を探る洞察力などです。
何らかの問題に対し、データを収集し、それを統計的に分析し、解決案を導き出します。
データサイエンティストは専門の職種としての需要が増えており、また、一般のビジネスマンでもデータサイエンティスト的な思考・行動が求められています。
セル内にプログラムを書き、Shift+Enterで実行
print(1+2)
式だけでも表示される
1+2
変数もそのまま書けば表示される
a=3+5 a
※別のセルにも変数の値は受け継がれる
ただし、式が自動表示されるのは最後のみ
1+2 3+5
pip install pandas
pandasをインポートし、DataFrameにデータを入れる。
DataFrameは二次元の表で行(index)と列(column)にラベルが付いている。
それぞれのデータはNumPyのndarray型で管理される。
リストのリストからDataFrame生成。
import pandas as pd import pandas as pd data = [ ["りんご", 100], ["みかん", 150] ] df = pd.DataFrame(data, index=[1, 2], columns=['商品名', '単価']) df
辞書から生成
import pandas as pd data = { "商品名" : ["りんご", "みかん", "いちご"], "単価" : [100,200,150] } df = pd.DataFrame(data, index = [1,2,3]) df
pandasをインポートし、read_csvで読み込みDataFrameに入れる。
import pandas as pd df = pd.read_csv("seiseki.csv") df
csv読み込みし、indexを特定の列にする。
import pandas as pd df = pd.read_csv("seiseki.csv", index_col="名前") df
# 最初の5個 df.head() # 最初の10個 df.head(10)
# スライスでも可能 df[:5]
# 最後の5個 df.tail() # 最後の10個 df.tail(10)
# スライスでも可能 df[-5:]
列は df[列名]、行は df.loc[インデックス名]、または df.iloc[番号]。番号は0から始まる。
# 1列のみ df["国語"] # 1行のみ df.loc["佐藤"] # 1行のみ df.iloc[0]
1行または1列の形で取り出したものは一次元のラベル付き配列「Series型」になる。
# 複数列取り出し df[["国語", "算数"]] # 列から値を取りだす df["国語"]["佐藤"] # 行・列で抽出 df.loc["佐藤"]["国語"] df.loc["佐藤"][["国語","算数"]] df.iloc[0]["国語"] df.iloc[0][["国語","算数"]]
df[df["国語"] >= 70] # 複数条件(and) df[(df["国語"] >= 70) & (df["算数"] >= 70)] # 複数条件(or) df[(df["国語"] >= 70) | (df["算数"] >= 70)] # query関数 df.query("国語 >= 70") # query関数(and) df.query("国語 >= 70 and 算数 >=70") # query関数(変数) ten = 70 df.query("国語 >= @ten")
# 指定行前のデータを参照 df["国語"].shift(1) # 前の行との差分を求める df["国語"].diff() # 前の行との変化の割合を求める df["国語"].pct_change()
# 左列を参照 df.shift(1, axis=1) # 左の行との差分を求める df[["国語","算数","理科","社会"]].diff(axis=1) # 左の行との変化の割合を求める df[["国語","算数","理科","社会"]].pct_change(axis=1)
df.loc["佐藤","算数"] = 90 # 行ごと変更 df.loc["佐藤"]=["A", "男", 70, 70, 70, 70] # 列の値を一括変更 df["算数"]=100 # 列の値を一括変更(計算) df["算数"]=df["国語"]+1
# 列追加 df["数学"]=0 # 行追加 df.loc["坂本"]=["B", "男", 70, 70, 70, 70] # 列をコピー df["キー"]=df["クラス"] # 列を追加して文字列の結合 df["キー"] = df["クラス"].str.cat(df.index)
# 行削除(インデックス) df.drop(3) # 行削除(インデックス) df.drop("山田") # 列の削除 df.drop("クラス", axis=1) # 列の削除 df.drop(columns=["クラス"])
# 1列変更 df = df.rename(columns={'クラス': '組'}) # 全て変更 df.columns = ["class", "sei", "kokugo", "sansu", "eigo", "shakai"]
df[列名].astype(型名)
# 文字を整数に df["国語"] = df["国語"].astype(int) # 文字を浮動小数点数に df["気温"] = df["気温"].astype(float)
日付型変換 df[列名] = pd.to_datetime(df[列名])
df["日付"] = pd.to_datetime(df["日付"]) # 年,月,日 を1つの日付列に df["日付"] = pd.to_datetime({ "year":df["年"], "month":df["月"], "day":df["日"] })
列全体で文字列のメソッドを使うには、df[列名].str.メソッド名
# 文字列の長さ df["クラス"].str.len()
列全体の日付のメソッドを使うには、df[列名].dt.メソッド名
# 年のみ df["日付"].dt.year # 月と日の列を作る df["月日"] = df["日付"].dt.strftime("%m/%d")
#整列 df.sort_values(["国語"], ascending=False)
df = df.sort_values(["国語"], ascending=False) #ilocでの行の取り出し df.iloc[0] #並べ替えたあとの0番目
# 列の並び替え df.reindex(columns=["国語","社会","理科","算数","性別","クラス"]) # 任意順の行の並び替え df.reindex(index=["鈴木","佐藤",・・])
# 逆順 (stepを-1に) df.iloc[::-1]
#行列反転 df.T
#列をインデックスに割り当て df = df.set_index("列名") # インデックス割り当て解除 df = df.reset_index()
#重複無しのデータ取得 df["クラス"].unique() #出現回数 df["クラス"].value_counts()
数値のみの項目に絞る場合、numeric_only=True を付ける
df["国語"].count() # 個数 df["国語"].sum() # 合計 df["国語"].mean() # 平均 df["国語"].median() # 中央値 df["国語"].mode() # 最頻値 df["国語"].min() # 最小値 df["国語"].max() # 最大値 df["国語"].var() # 分散 df["国語"].std() # 標準偏差(ばらつきを示す。平均からどれぐらい離れているか) df["累計"]=df["国語"].cumsum() #累計
df["国語"].quantile(0.25) #第一四分位数 df["国語"].quantile(0.50) #第二四分位数 = 中央値 df["国語"].quantile(0.75) #第三四分位数
count、mean、std、min、25%、50% 75% max
df.describe()
0.7~ 強い相関あり
0.4~ 相関あり
0.2~ 弱い相関あり
df.corr()
2つの平均値に有意差があるかどうかを検定する。
scipy.statsのttest_ind関数を使用する
オプションのalternativeは片側検定の場合指定。大きいかどうかなら greater、小さいかどうかなら less。どちらでもいい場合、指定しない。
pが0.05未満なら統計的に有意となる。
dfa = df[df["クラス"]=="A"]["国語"] dfb = df[df["クラス"]=="B"]["国語"] from scipy import stats t, p = stats.ttest_ind(dfa, dfb, equal_var=False, alternative='less') print(t,p) if p < 0.05: print('統計的に有意') else: print('統計的に有意ではない')
grp = df.groupby("クラス") grp["国語"].mean() # クラスごとの国語の平均点
df.groupby("クラス").mean() # クラスごとの全ての平均点
他にも sum(合計)、max(最大)、min(最小)、std(標準偏差)、count(件数)、describe(基本統計量)などが使用できる。
#複数の統計処理 grp.agg(['sum', 'mean', 'std'])
国語をクラス、性別ごとに平均を求める
df.pivot_table(values="国語", index="クラス", columns="性別")
小計・総計も表示
df.pivot_table(values="国語", index="クラス", columns="性別", margins=True)
平均以外の時にはaggfuncで関数を指定する
import numpy as np # 最大値 df.pivot_table(values="国語", index="クラス", columns="性別",aggfunc=np.max)
数を数えるときにはpd.crosstab が使える
# クラス、性別でカウント pd.crosstab(df["クラス"],df["性別"])
# 欠損値があるかをtrue/falseで表示 df.isnull() # 欠損値のある列を確認 df.isnull().any(axis=0) # 欠損値のある行を確認 df.isnull().any(axis=1) # 欠損値のある行の数を確認 df.isnull().sum() # 欠損値のある行を削除 df = df.dropna() # 国語がある行を残し欠損値のある行を削除 df = df.dropna(subset=["国語"])
# 欠損値を0で穴埋め df["国語"] = df["国語"].fillna(0) # 欠損値を平均で穴埋め heikin = df["国語"].mean() df["国語"] = df["国語"].fillna(heikin) # 欠損値を一つ前の値で穴埋め df = df.fillna(method='ffill')
# 文字列の置換 名前の列の"田"を"本"に df["名前"] = df["名前"].str.replace("田", "本") # 正規表現での文字列一部置換 名前の列の"田"を"本"に df["名前"] = df.replace({"名前":{"田", "本"}}, regex=True)
# 全列での置換 80を800に置換 df = df.replace({80:800}) # 数値の置換 国語の列の80を800に置換 df = df.replace({"国語":{80:800}})
# 0と1への置き換え # データがAとBの場合、A列とB列が出来て、それぞれ0と1が入る。 x = pd.get_dummies(df['クラス']) # 最初の列(A列)を削除 x = pd.get_dummies(df['クラス'], drop_first=True) # 元のdfに反映するには、連結する df = pd.concat([df, x], axis=1)
# 数値への置き換え # データがAとBの場合、Aが0、Bが1のように列を作る # groupbyでグループ化し、ngroup()でgroupの番号を取得する。 df['クラスID'] = df.groupby(['クラス']).ngroup()
# 全ての列を小数点以下2桁に四捨五入 df = df.round(2) # 特定の列(例:気温)を小数点以下2桁に四捨五入 df = df.round({'気温': 2})
同じインデックス同士を結合する
df1 = df[["国語","算数"]] df2 = df[["理科","社会"]] df1.join(df2)
同じ列名をキーにして結合する
df = pd.read_csv("seiseki.csv") df1 = df[["名前","国語","算数"]] df2 = df[["名前","理科","社会"]] # 両方に「名前」があるので名前をキーにする pd.merge(df1,df2)
キーを指定して結合
df = pd.read_csv("seiseki.csv") df1 = df[["氏名","国語","算数"]] df2 = df[["名前","理科","社会"]] pd.merge(df1, df2, left_on='氏名', right_on='名前')
単純結合。concatでaxis=1を指定すると横結合。
df1 = df["国語"] df2 = df["社会"] pd.concat([df1,df2], axis=1)
concatでaxisを指定しない、またはaxis=0を指定すると縦結合。
df1 = df.query("クラス=='A' and 性別=='男'") df2 = df.query("クラス=='B' and 性別=='女'") pd.concat([df1,df2])
# インデックスと行 for index,row in df.iterrows(): print(index,row["国語"]) # 行をリストで for row in df.values: print(row[0]) # 列をリストで for col in df.columns: print(col)
pip install mlxtend
import pandas as pd # サンプルデータの生成 data = {'ID':[1,2,3,4,5,6], 'Onion':[1,0,0,1,1,1], 'Potato':[1,1,0,1,1,1], 'Burger':[1,1,0,0,1,1], 'Milk':[0,1,1,1,0,1], 'Beer':[0,0,1,0,1,0]} df = pd.DataFrame(data)
以下で分析
df2 = df.drop('ID', axis=1) from mlxtend.frequent_patterns import apriori from mlxtend.frequent_patterns import association_rules # Aprioriの適用 最小サポート0.3 frequent_itemsets = apriori(df2, min_support=0.3, use_colnames=True) # アソシエーションルールの抽出 rules = association_rules(frequent_itemsets) rules
antecedents | 前提条件(この商品が買われた場合) |
---|---|
consequents | 結果(前提条件の商品が買われたとき、一緒に買われる商品) |
antecedent suppor | 前提条件のアイテムセットが取引に含まれる割合 |
consequent support | 結果のアイテムセットが取引に含まれる割合 |
support | antecedents と consequents が同時に出現する割合 |
confidence | antecedents が起きたときに consequents も起きる確率 |
lift | 関連性の強さ(1より大きいと正の相関) |
representativity | ルールがデータ全体をどの程度代表しているか |
leverage | 期待される共起頻度との差 |
conviction | ルールの確実性(大きいほど信頼できる) |
#csv読み込み df = pd.read_csv("seiseki.csv") #csv書き込み df.to_csv("out.csv") #インデックス無し df.to_csv("out.csv",index=False)
事前にopenpyxlをインストールする。
pip install openpyxl
#Excel読み込み df = pd.read_excel("seiseki.xlsx") df
#Excel書き込み df.to_excel("out.xlsx")
read_sql_query で読み込む。
import mysql.connector con = mysql.connector.connect( user = 'root', password = '', database = 'hanbai' ) import pandas as pd df = pd.read_sql_query("SELECT * FROM shouhin",con) df
import sqlite3 dbname = 'hanbai.db' con = sqlite3.connect(dbname) import pandas as pd df = pd.read_sql_query("SELECT * FROM shouhin",con) df
まずtabulaのインストールを行う。
pip install tabula-py
以下のようにして取得できる。
import pandas as pd import tabula dfs = tabula.read_pdf('ファイル名', lattice=True, pages = 'ページ番号') # このページの最初の表 df = dfs[0]
read_htmlでURLを指定すると、そこにあるテーブルを全てDataTableにし、そのリストを返す。
まず pip install lxml でlxml をインストールしておく。
例としてYahoo!の熊本市のアメダスを読み込む。
import pandas as pd url = 'https://weather.yahoo.co.jp/weather/amedas/43/86141.html' dfs = pd.read_html(url) df = dfs[0] df
header=0で列名を設定。わかりにくい場合、df.columnsで設定する。
import pandas as pd url = 'https://weather.yahoo.co.jp/weather/amedas/43/86141.html' dfs = pd.read_html(url,header=0) df = dfs[0] df.columns = ['日付','時刻','気温','降水量','風向','風速','日照時間','積雪深'] df
import matplotlib.pyplot as plt import seaborn as sns sns.set_theme(font=["Meiryo"]) df = df.iloc[::-1] # 逆順にする # グラフ表示 df.plot(x="時刻",y=["気温","日照時間"]) plt.title('熊本市 過去24時間の気温と日照時間') plt.show()
※欠損がある場合、データ型は文字列になる場合があるので、そのときには数値項目に変換しておく
df["気温"] = df["気温"].astype("float") df["日照時間"] = df["日照時間"].astype("float")