Python データ処理ライブラリ Pandas の導入とそのデータ型

# Pandas に 関して

「Pandas」は Python のライブラリで、データを効率的に解析するためのライブラリです。

「行列的」にデータを扱う事ができ、データ処理を強力に実行できます。

マニュアル等は公式サイトを参照してください。

[Python Data Analysis Library — pandas: Python Data Analysis Library](https://pandas.pydata.org/)

# Pandas の インストール

以下のリンク先の手順で環境を構築した場合はインストールは不要です。

- [Python 環境構築手順 Windows編 - Qiita](https://qiita.com/xza/items/14738b2b05d1e3f3cde6)

その他の方法で環境を構築した場合は以下の手順が必要です。

```sh
pip install pandas
```

# Pandas の データ型の理解

Pandas を利用する場合はまずはデータ型を理解する必要があります。

Pandas は以下の3種類のデータ構造が扱えます。

型名|概要
---|---
Series|1次元データ
DataFrame|2次元データ
Panel|3次元データ

まずは、ライブラリの import をします。


```python
import pandas as pd
```

# Series

基本は「Series」です。

Series は「1次元データ」を扱うためのPandasのデータ型です。

list から生成できます

```python

cnt = pd.Series([10, 20, 30, 50, 80, 130])
cnt

```

```
    0     10
    1     20
    2     30
    3     50
    4     80
    5    130
    dtype: int64
```

型は type で確認できます。

```python
type(cnt)
```

```
    pandas.core.series.Series
```

値を取得する場合は「values」で簡単に取得できます。

```python
cnt.values
```

```
    array([ 10,  20,  30,  50,  80, 130])
```



index を取得できます。デフォルトだと rangeになっています。

```python
cnt.index
```

```
    RangeIndex(start=0, stop=6, step=1)
```

index に値を指定する事も可能です。

```python
cnt = pd.Series([10, 20, 30, 50, 80, 130],
        index=['a', 'b', 'c', 'd', 'e', 'f'])
cnt
```

```
    a     10
    b     20
    c     30
    d     50
    e     80
    f    130
    dtype: int64
```

dictのように取得も可能です。

```python
cnt['b']
```

```
    20
```

list の内包表記が利用できます。以下は index を利用して、判定しています。

```python
[v in ('a', 'd') for v in cnt.index]
```

```
    [True, False, False, True, False, False]
```


True/False の list を渡すと、True の値のみ抽出が可能です。

```python
cnt[[v in ('a', 'd') for v in cnt.index]]
```

```
    a    10
    d    50
    dtype: int64
```

内部的には deep copy されているため、操作した後でも元の値は変化しません。

```python
cnt
```

```
    a     10
    b     20
    c     30
    d     50
    e     80
    f    130
    dtype: int64
```

value の比較で抽出も可能です。

```python
cnt[cnt > 100]
```

```
    f    130
    dtype: int64
```

最初 list から作成しましたが、dict から作成する事も可能です。

```python
d = {'a': 300, 'b': 400}
newcnt = pd.Series(d)
newcnt
```

```
    a    300
    b    400
    dtype: int64
```

二つの Series は 加算する事ができますが、index が不足した部分は 「NaN」になります。

NaN は「計算不能」を表す値で、 Null とは多少異なる数値です。Null に近い flaot です。

pandas の場合、列の型が混在すると問題ですので、NaN でないと型が混在してしまいます。

型混在によるバグやエラーは対処がしずらい場合がありますので、注意してください。

```python

cnt + newcnt
```

```
    a    310.0
    b    420.0
    c      NaN
    d      NaN
    e      NaN
    f      NaN
    dtype: float64
```


括弧で囲んで、関数を適用できます。「isnull」は「NaN or Null」かどうか判定します

```python
(cnt + newcnt).isnull()
```

```
    a    False
    b    False
    c     True
    d     True
    e     True
    f     True
    dtype: bool
```



# DataFrame

DataFrame は2次元を扱うためのPandasのデータ型です。

DataFrame は Series を「列」にもつ型です。

```python
data = pd.DataFrame([cnt, newcnt])
data
```

<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>a</th>
      <th>b</th>
      <th>c</th>
      <th>d</th>
      <th>e</th>
      <th>f</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>10.0</td>
      <td>20.0</td>
      <td>30.0</td>
      <td>50.0</td>
      <td>80.0</td>
      <td>130.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>300.0</td>
      <td>400.0</td>
      <td>NaN</td>
      <td>NaN</td>
      <td>NaN</td>
      <td>NaN</td>
    </tr>
  </tbody>
</table>
</div>


型も確認してみます.

```python

type(data)
```

```
    pandas.core.frame.DataFrame
```

直接生成もできます。

list から生成する場合は columns を指定すると列名が指定できます。

```python
data_a = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['a', 'b'])
data_a
```




<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>a</th>
      <th>b</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>1</td>
      <td>2</td>
    </tr>
    <tr>
      <th>1</th>
      <td>3</td>
      <td>4</td>
    </tr>
    <tr>
      <th>2</th>
      <td>5</td>
      <td>6</td>
    </tr>
  </tbody>
</table>
</div>



dict で生成する場合は、「行」ではなく「列」毎に値を生成します。

dictのkeyが「列」名、valueが「行」の数分値が必要になります。valueの数に不足があるとエラーになります。

```python

d = {
    'a': [1, 2, 3],
    'b': [5, 6, 7],
}
data_b = pd.DataFrame(d)
data_b
```


<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>a</th>
      <th>b</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>1</td>
      <td>5</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2</td>
      <td>6</td>
    </tr>
    <tr>
      <th>2</th>
      <td>3</td>
      <td>7</td>
    </tr>
  </tbody>
</table>
</div>




```python
data
```

<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>a</th>
      <th>b</th>
      <th>c</th>
      <th>d</th>
      <th>e</th>
      <th>f</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>10.0</td>
      <td>20.0</td>
      <td>30.0</td>
      <td>50.0</td>
      <td>80.0</td>
      <td>130.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>300.0</td>
      <td>400.0</td>
      <td>NaN</td>
      <td>NaN</td>
      <td>NaN</td>
      <td>NaN</td>
    </tr>
  </tbody>
</table>
</div>


特定列だけ抽出してみます。

```python
data[['b', 'a']]
```

<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>b</th>
      <th>a</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>20.0</td>
      <td>10.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>400.0</td>
      <td>300.0</td>
    </tr>
  </tbody>
</table>
</div>


内部のデータ型を取れます。

```python

data.dtypes
```

```
    a    float64
    b    float64
    c    float64
    d    float64
    e    float64
    f    float64
    dtype: object
```

列の値を取得したい場合は、以下2種類の方法で取れます。

プログラムで、変数を利用して取得する場合等は、key を利用した取得の方が利用するでしょう。

```python

data.a
data['a']
```

```
    0     10.0
    1    300.0
    Name: a, dtype: float64
```

取得できた物が Series である事も確認してみます。

```python

type(data['a'])
```

```
    pandas.core.series.Series
```

列は列名で取得できますが、行は「loc」で取得します。

```python

data.loc[1]
```

```
    a    300.0
    b    400.0
    c      NaN
    d      NaN
    e      NaN
    f      NaN
    Name: 1, dtype: float64
```

行で取得しても 型は Series です。

```python

type(data.loc[1])
```

```
    pandas.core.series.Series
```


# Panel

「Panel」は3次元データを扱えます。

2次元データのDataFrameがSeries で構成されていた事から予想できるように、「Panel」は「DataFrame」から構成されます。


```python
data
data_a
data_b

pd.Panel({'1': data, '2': data_a, '3': data_b})
```

```
    <class 'pandas.core.panel.Panel'>
    Dimensions: 3 (items) x 3 (major_axis) x 6 (minor_axis)
    Items axis: 1 to 3
    Major_axis axis: 0 to 2
    Minor_axis axis: a to f
```


3次元のデータを利用すると、時系列データの分析など、DataFrameを多層に保持するデータの分析が気軽にできます。

扱いは DataFrme と同じ感覚で扱えます。

# 様々なデータを扱う

少し長くなってきたので、別の文章で記述します。

以下のリンク先で続きを記述します。

- [Pandas で様々なファイルを読み込み操作する - Qiita](https://qiita.com/xza/items/8bdcf3f62ce2ae2e6c21)
- [Python Pandas を Excel代わりに利用してデータ操作 - Qiita](https://qiita.com/xza/items/2fa962260c229e39ea4c)

# 書いた人に関して
[Tech Fun株式会社](http://www.techfun.co.jp/)スペシャリスト、xza です。

社内で開催した初学者向け勉強会で利用した資料等を公開しています。