🐡

記述統計学

2023/01/30に公開約14,200字

あらまし

機械学習エンジニアに未経験から転職した。研修期間に学んだことを書きます。

📌 文系にもわかりやすいように、わかりやすく書く。

🔗Outline

1.データを分類する
2.データの特徴を調べる

📘Instructions

データを分類する

データにはその特徴別に種類があります。それらを識別することで、その特徴にあった記述や推測が可能になります。

  1. カテゴリー型(質的変数 or Categorical Variables)
  2. 数値型(量的変数 or Numeric Variables)
    1. 離散型(Discrete Variables)
    2. 連続型(Continuous Variables)

カテゴリー型は性別や国籍などあるカテゴリーに属するデータです。対して、数値型はその名の通り数値で表現されたデータになります。

数値型はさらに、離散型と連続型に分けることができます。離散型はサイコロの目のように飛び飛びの値では取れない変数。つまり、小数点などに細かく値をとれない変数となります。対して、連続型はどこまでも細かく数値をとることが可能です。

データの特徴を調べる

  1. 統計量
    1. 分散

      S^2 = \frac{1}{n}\Sigma_{i=1}^{n}(x_i-\bar{x})^2

      S^2 = 分散
      x_i = _i個目のデータ
      \bar{x} = データの平均
      n = データの数量

      分散 = 分布のひろがりを表す統計量

    2. 不変分散

      S^2 = \frac{1}{n-1}\Sigma_{i=1}^{n}(x_i-\bar{x})^2

      不変分散 = 分散よりも少し大きい値になっており、分散よりも母分散に近づくとされている

    3. 標準偏差

      \sigma = \sqrt{S^2}

      S^2 = 分散
      \sigma = 標準偏差

基礎統計量とは、データ分布の特徴を数値で表す指標です。有名なものだと、平均や中央値などがあります。これらの説明は割愛しますが、統計学において大事な基礎統計量の一つである、分散と標準偏差について解説します。

標準偏差とは分布のひろがりや散らばり具合を表す統計量です。推測などをする際に、データが散らばっていると推測しづらくなります。二乗している理由は、負の値が出てしまうと正の値と打ち消しあってしまい、ばらつき具合を加算していかなくなるためです。

しかし、このままでは二乗している関係で、単位が変わってしまいます。身長を例に出すとcm^2が単位となってしまいます。そこで分散を√することでcmで考えることができます。この値が標準偏差です。

  1. 可視化

    1. 1変数
      • ヒストグラム
        • スニペット

          #distplotはヒストグラムを描写
          sns.distplot(train['column'])
          
          #数値型のみのヒストグラムをforループで複数描写
          cols = 3
          rows = 3
          num_cols = df.select_dtypes(exclude='object').columns
          fig = plt.figure( figsize=(cols*5, rows*5))
          for i, col in enumerate(num_cols):
              
              ax=fig.add_subplot(rows,cols,i+1)
              
              sns.histplot(x = df[col], ax = ax)
              
          fig.tight_layout()  
          plt.show()
          
        • 特徴

          1. データの範囲や峰の数、データの集中具合がわかる
          2. 特徴量の歪度がわかる
          3. 異常値の有無がわかる


    2. 2変数
      1. 数値型
        • 散布図
          • スニペット

            sns.jointplot(x='numeric_column', y='numeric_column', hue = "column", data=df)
            
          • 特徴

            1. 当てはめるモデルを予測しやすい
            2. 外れ値がわかる
            3. kind='reg’を入れることで、線形回帰を描写できる

        • 棒グラフ
          • スニペット

            #countplotは棒グラフを描写
            sns.countplot(x="column",y='numeric_column',hue="column", data=df)
            
            #barplotは棒グラフ+信頼区間をグラフ化
            sns.barplot(x="column",y='numeric_column', data=df)
            
          • 特徴

            1. データの範囲や峰の数、データの集中具合がわかる
            2. 特徴量の歪度がわかる
            3. 異常値の有無がわかる

        • KDEプロット
          • スニペット

            #KDE単体
            sns.kdeplot(x='column', data=df, hue='column')
            
            #ヒストグラム+KDE
            sns.histplot(x='column', data=df, kde=True)
            
          • 特徴

            1. ある変数の分布を別ものと比較できる

        • ラグプロット
          • スニペット

            #ラグプロット+ヒストグラム+KDE
            sns.rugplot(x='column', data=df, height=.03, color='darkblue')
            sns.histplot(x='column', data=cars, kde=True)
            
          • 特徴

            1. 異常値がどこにあるかわかる

        • 箱ひげ図
          • スニペット

            #通常
            sns.boxplot(x=df['cplumn'])
            
            #多くの箱ひげ図を出すとき
            cols = 3
            rows = 3
            num_cols = df.select_dtypes(exclude='object').columns
            fig = plt.figure(figsize= (15,9))
            for i, col in enumerate(num_cols):
                
                ax=fig.add_subplot( rows, cols, i+1)
                
                sns.boxplot(x=df[col], ax=ax)
                
            fig.tight_layout()  
            plt.show()
            
            #カウントグラフと箱ひげ図を上下に並べて比較する
            fig = plt.figure()
            
            #カウントグラフ
            ax1 = fig.add_subplot(2,1,1) 
            sns.countplot(data = df, x = 'column', ax = ax1)
            
            #箱ひげ図
            ax2 = fig.add_subplot(2,1,2) 
            sns.boxplot(data = df, x='column', y='column2' , ax = ax2)
            
          • 特徴

            1. 数値型特徴量の分布、中心、歪度、外れ値、最大値、最小値などわかる
            2. ヒストグラムより詳細でないが、小さく素早くプロット可能

        • バイオリンプロット
          • スニペット

            sns.violinplot(data = df, x='column', y='column2')
            
          • 特徴

            1. バイオリンプロットとKDEプロットの特徴を持つ

        • ストリッププロット
          • スニペット

            sns.stripplot(x=df["cplumn"])
            
          • 特徴

            1. 外れ値
            2. 箱ひげ図と違い相対的な中心を確立するのが難しく、より小さなデータセットに最適


      2. カテゴリー型
        • クロス集計表
          • スニペット

            #pandasで実装
            #2変数
            pd.crosstab([df["categorical_column"],df["categorical_column"])
            #3変数
            pd.crosstab([df["categorical_column"],df["categorical_column"]], df["categorical_column"])
            
          • 特徴

            1. シンプルに結果がわかる

        • カウントプロット
          • スニペット

            #基本形1
            sns.countplot(x="column", data=data)
            
            #オブジェクトクラスの数量でソートしたいとき
            data['categorical_class'].value_counts().plot(kind="bar")
            
            #複数のカテゴリー変数をforループでプロットする
            cols = 4
            rows = 1
            fig = plt.figure(figsize= (16,6))
            all_categs = df.select_dtypes(include='object')
            cat_cols = all_categs.columns[all_categs.nunique() < 10]
            for i, col in enumerate(cat_cols):
                
                ax=fig.add_subplot(rows, cols, i+1)
                
                sns.countplot(x=cars[col], ax=ax)
                
                plt.xticks(rotation=45, ha='right')
                
            fig.tight_layout()  
            plt.show()
            
          • 特徴

            1. データ中に各クラスが何回現れるかわかる

        • パイチャート
          • スニペット

            #seabornにはない
            df_column_val = df['column'].value_counts()
            plt.pie(df_column_val, labels=df.index, autopct="%.0f%%");
            
          • 特徴

            1. シンプルで分かりやすい
            2. 可視化コミュニティではあまり人気がない
              1. グループが4つ以上になると、グラフが乱雑に見えること
              2. スライスの幅が直感的にわかりにくい場合があること



  2. 相関

    • 数値型

      • ピアソンの積率相関係数

        r =\frac{\Sigma{(x_i-\bar{x})(y_i-\bar{y})}}{\sqrt{\Sigma{(x_i-\bar{x})^2(y_i-\bar{y})^2}}}

        r = 相関係数
        x_i = x変数の値
        \bar{x} = x変数の平均
        y_i = y変数の値
        \bar{y} = y変数の平均

      • スニペット

        #ヒートマップで比較する場合
        
        #import seaborn as sns
        #import matplotlib.pyplot as plt
        #%matplotlib inline
        
        CONTINUOUS_VARIABLES = ["column",
                               "column",
                               "column",
                               "column",
                               "column"]
        
        #CONTINUOUS_VARIABLESの新しいデータフレームを作成する
        cont_variables_dataframe = **df**[CONTINUOUS_VARIABLES]
        #CONTINUOUS_VARIABLESの相関を計算する
        cont_variables_correlation = cont_variables_dataframe.corr()
        #ヒートマップにしてプロット
        ax = sns.heatmap(cont_variables_correlation,
                         annot=True,
                         linewidths=.5,
                         cmap="YlGnBu",
                         square=True
                        );
        



    • カテゴリー型

      • クラメール連関係数

        V = \sqrt{\frac{\chi^2}{n×min(r-1,c-1)}}

        V = 相関係数
        \chi^2 = カイ二乗値
        n = サンプルサイズ
        r = 行数
        c = 列数

      • スニペット

        #クラメールV
        def cramersV(x, y):
             table = np.array(pd.crosstab(x, y)) #クロス集計
             n = table.sum() #実測度数
             colsum = table.sum(axis=0) #縦計
             rowsum = table.sum(axis=1) #横計
             expect = np.outer(rowsum, colsum) / n #期待度数
             chisq = np.sum((table - expect) ** 2 /expect) #カイ二乗値
             return np.sqrt(chisq / (n * np.min(table.shape) -1)) #クラメール連関係数
         
         name = []
         result = []
         
         for column_name, item in df.iteritems():
             name.append(column)
             x = cramersV(df[x], item)
             result.append(x)
         
         # データフレーム化
         df_result = pd.DataFrame({'factor':name, 'cramersV':result})
         df_result
        
        #カテゴリー型変数の相関をforループで描写する
        
        #from scipy import stats
        
        CATEGORICAL_VARIABLES = ["column",
                               "column",
                               "column",
                               "column",
                               "column"]
        
        for c in CATEGORICAL_VARIABLES:
            if c not in ["column", "column", "column"]:#2値データの選択
                correlation = stats.pearsonr(df[c], df["y_column"])#ピアソンの相関係数
            else:
                correlation = stats.pointbiserialr(dataset[c], df["y_column"])#点双列相関係数
            print("Correlation of %s to **column** is %s" %(c, correlation))
        
        #カテゴリー変数をラベルエンコーディングする場合
        label_encoder = LabelEncoder()
        data.iloc[:,0] = label_encoder.fit_transform(data.iloc[:,0]).astype('float64')
        corr = data.corr()
        sns.heatmap(corr)
        


    相関係数は2種類のデータ間の関連性の強さを示す指標で、どれだけ直線の関係に近いかわかる。相関係数が1に近いと正の相関が強く、-1に近いと負の相関が近い。0に近いと相関が薄い。ただし、外れ値に影響されるので注意が必要。

📄References

  1. https://qiita.com/zumitan/items/dd4bfc7e7d5624c74bee
  2. https://www.kaggle.com/code/nextbigwhat/eda-for-categorical-variables-a-beginner-s-way/notebook
  3. https://towardsdatascience.com/8-seaborn-plots-for-univariate-exploratory-data-analysis-eda-in-python-9d280b6fe67f
  4. https://www.kaggle.com/code/vmalyi/finding-the-most-correlating-variables/notebook
  5. https://www.kaggle.com/code/bbloggsbott/feature-selection-correlation-and-p-value
  6. https://zenn.dev/ohrzw/articles/a9a818e71c3278

Discussion

ログインするとコメントできます