python初心者のpandas勉強記録１～Seriesについて～

# １．はじめに

pandasについて勉強を始めました。基本的なところから押さえていこうと思います。

# ２．そもそもpandasとは？

[wikipedia](https://ja.wikipedia.org/wiki/Pandas)には次のように書いてありました：

>Pandasは、プログラミング言語Pythonにおいて、データ解析を支援する機能を提供するライブラリである。特に、数表および時系列データを操作するためのデータ構造と演算を提供する。PandasはBSDライセンスのもとで提供されている。

よくわからないけど、データ解析をするにはあるととても便利なのでしょう。きっと。

# ３．使い方

基本的な使い方を押さえていきます。ただ、どうもpandasの機能はめちゃめちゃたくさんあるそうなので、おいおい追記していこうかと思います。

とにもかくにもまずはインポート：

```python
import pandas as pd
```

## ①Series

pandasには、Seriesという型があるそうです。numpyの配列と密接に関連していることが後でわかります。

まずはインポートします：

```python
from pandas import Series
```

### Seriesの作り方とインデックス

Seriesでは、１次元の配列を作ることができます：

```python
ser = Series([3,6,9,12])
ser
>>>0     3
   1     6
   2     9
   3    12
   dtype: int64
```

左側にはインデックス番号が振られていることがわかりますね。ここから値だけを取り出すには、`values`属性を使います：

```python
ser.values
>>>array([ 3,  6,  9, 12], dtype=int64)
```

はい、ここでnumpyの配列が出てきました。Seriesとnumpyが密接に関係していることがうかがえます。

同じようにインデックスを参照するときは`index`属性を用います：

```python
ser.index
>>>RangeIndex(start=0, stop=4, step=1)
```

なんか変なのが出ましたが、意味は分かります。スライスと同じですね。

インデックスはもちろん自分で決めることができます：

```python
ser = Series([1,2,3,4], index=["A", "B", "C", "D"])
ser
>>>A    1
   B    2
   C    3
   D    4
   dtype: int64
```

先ほどはインデックスに0から始まる数字が振られていましたが、見事に自分で決めたインデックスを付けることができています。

各データには、インデックスを使ってアクセスすることができます。また、大小比較などの条件を割り振ることもできます：

```python
ser = Series([1,2,3,4], index=["A", "B", "C", "D"])
#インデックスでアクセス
ser["A"]
>>>1
#条件(numpyの配列でも似たことができる)
ser > 2
>>>A    False
   B    False
   C     True
   D     True
   dtype: bool
#Trueの部分の要素のみ取り出す
ser[ser > 2]
>>>C    3
   D    4
   dtype: int64
```

numpyで同じようなことを経験していればとっつきやすいかと思いますが、見ればなるほどなと思う操作ではないでしょうか。


### Seriesと辞書

また、Seriesはpythonの辞書型のように使うこともできます。例えば、与えられた文字列がインデックスとして含まれているかどうかは、`in`を使えばいいのでした。Seriesでも使えます：

```python
ser = Series([1,2,3,4], index=["A", "B", "C", "D"])
"A" in ser
>>>True
"F" in ser
>>>False
```

to_dict()メソッドを用いると、Seriesから辞書を作ることもできます。逆に、辞書からSeriesを作ることもできます：

```python
ser = Series([1,2,3,4], index=["A", "B", "C", "D"])

#Seriesから辞書
ser.to_dict()
>>>{'A': 1, 'B': 2, 'C': 3, 'D': 4}

#辞書からSeries
dic = {"tanaka": 20, "yamashita": 30, "yoshida": 50}
ser = Series(dic)
>>>tanaka       20
   yamashita    30
   yoshida      50
   dtype: int64
```

言われてみれば似たような形をしているので、相互に変換できるのは何かと都合がよさそうですね。

さらにさらに、辞書からSeriesを作る際、インデックスを追加することができます：

```python
dic = {"tanaka": 20, "yamashita": 30, "yoshida": 50}
member = ["tanaka", "yamashita", "yoshida", "nakamura"] #nakamuraを追加している
ser = Series(dic, index=member)
ser
>>>tanaka       20.0
   yamashita    30.0
   yoshida      50.0
   nakamura      NaN
   dtype: float64
```

元の辞書には"nakamura"という要素はないのでインデックスを追加しても、値はなしになっていますね。このことは、`pandas.isnull`関数でも確認できます：

```python
pd.isnull(ser)
>>>tanaka       False
   yamashita    False
   yoshida      False
   nakamura      True
   dtype: bool
```

これも便利ですね。これと全く逆の結果になる関数で`pandas.notnull`というのもあります。参考までに。

### Seriesのソート

ここでは、Seriesをソートする方法についてまとめておこうと思います。

その前に、説明の都合でnumpyを使いたいのでインポートしておきます：

```python
from numpy.random import randn
```

まずは簡単なSeriesを作成しておきましょう：

```python
ser = Series(randn(5), index = ["E", "C", "A", "B", "D"])
ser
>>>E   -0.511028
   C    0.100569
   A    0.834416
   B   -0.207201
   D   -2.755599
   dtype: float64
```

上ではあえてインデックスの順番をぐちゃぐちゃにしています。

インデックスについてソートするには、`sort_index`メソッドが有効です：

```python
ser.sort_index()
>>>A    0.834416
   B   -0.207201
   C    0.100569
   D   -2.755599
   E   -0.511028
   dtype: float64
```

インデックスがアルファベット順になりました。

また、値でソートする場合には、`sort_values`メソッドが有効です：

```python
ser.sort_values()
>>>D   -2.755599
   E   -0.511028
   B   -0.207201
   C    0.100569
   A    0.834416
   dtype: float64
```

`sort_values`と合わせて押さえておきたいのが、`rank`というメソッドです。これは、「そのデータが小さいほうから何番目か」を数えてくれるメソッドです。実際に見てみましょう：

```python
ser.rank()
>>>E    2.0
   C    4.0
   A    5.0
   B    3.0
   D    1.0
   dtype: float64
```

先ほどのsort_valuesの実行結果と見比べてみてください。例えば、インデックスDのデータは先頭に来ていたので、上で値が「1.0」になっていますね。



# 次回

ちょっと長くなってしまったので、３．使い方　の続きはまた別の記事にしようと思います。次はpandasでテーブルを操作する方法をまとめようと思います。