pandasによるDataFrameの基本操作

**DataFrame.map()による列の追加及び列のデータの更新**
**リスト内包表記による列の追加及び列のデータの更新**
を追加しました。(2018/01/02)


----


pandasによるDataFrameの操作について随時まとめていきます。
基本的なことばかりですが、ご了承ください。。


```python
import pandas as pd #pandasライブラリをimport
import seaborn as sns #seabornライブラリをimport
df=sns.load_dataset("iris") #dfにiris データセットを代入
```

```python
df.head() #dfの確認
```
```python
   sepal_length  sepal_width  petal_length  petal_width species
0           5.1          3.5           1.4          0.2  setosa
1           4.9          3.0           1.4          0.2  setosa
2           4.7          3.2           1.3          0.2  setosa
3           4.6          3.1           1.5          0.2  setosa
4           5.0          3.6           1.4          0.2  setosa
```
#DataFrame.loc()、DataFrame.iloc()を用いた列選択、行選択
DataFrame.loc()は***列名、インデックス名***による選択を行う。
DataFrame.iloc()は***データの位置番号***による選択を行う。

```python
df.loc[:,["sepal_length","petal_width"]].head()
#全ての行や列を指定するときは":"を用いる　※:の前後には最初の行の番号と最終行の番号が省略されている
```
```python
   sepal_length  petal_width
0           5.1          0.2
1           4.9          0.2
2           4.7          0.2
3           4.6          0.2
4           5.0          0.2
```

```python
df.iloc[1,2]#行、列は1行目ではなく、0行目から始まるので、"petal_length"の2つめのデータが出力される
```

```python
1.3999999999999999
```
#DataFrame[]を用いた列選択
[]内に列名を指定することで、列毎にデータを選択できる


```python
df["sepal_length"]
```

```python
0      5.1
1      4.9
2      4.7
3      4.6
4      5.0
5      5.4
6      4.6
~ ~ ~ ~ ~(以下、長いので省略)
```
複数の列を指定するには、列名を[]で囲む

```python
df[["sepal_length","petal_width"]].head()
```


```python
   sepal_length  petal_width
0           5.1          0.2
1           4.9          0.2
2           4.7          0.2
3           4.6          0.2
4           5.0          0.2
```

#DataFrame.drop()を用いた***列***の削除
列を削除する場合、axis引数を***1***に指定する

```python
df.drop(["sepal_length","petal_width"],axis=1).head()
```

```python
   sepal_width  petal_length species
0          3.5           1.4  setosa
1          3.0           1.4  setosa
2          3.2           1.3  setosa
3          3.1           1.5  setosa
4          3.6           1.4  setosa
```

#eval()によるSeriesデータ,DataFrameの列データの計算
##Series.eval()によるSeriesデータの計算
Series.eval()の()内は文字列で指定する（つまり""もしくは''で囲む）

```python
ser1=df.iloc[:,1] #series型のデータを作成（これは"sepal_width"列のデータです）
pd.eval("ser1+ser1")
```

```python
0      7.0
1      6.0
2      6.4
3      6.2
4      7.2
5      7.8
6      6.8
~ ~ ~ ~ ~(以下、長いので省略)
```
##DataFrame.eval()による列データの計算
同様に、()内は""で囲みます。
***列名だけ***で記述できるところがポイントです。

```python
df.eval("sepal_length / petal_length")
```

```python
0      3.642857
1      3.500000
2      3.615385
3      3.066667
4      3.571429
5      3.176471
6      3.285714
7      3.333333
~ ~ ~ ~ ~(以下、長いので省略)
```
##DataFrame.eval()による列の追加及び列のデータの更新
DataFrame.eval()を用いて、新たに列を追加したり、列のデータを更新できます。

```python
df.eval("sepal_length2=sepal_length**2",inplace=True) #sepal_lengthの2乗を計算し、sepal_length2という列に代入
df.eval("petal_width=1",inplace=True) #petal_width列のデータを1に更新
df.head()
```

```python
   sepal_length  sepal_width  petal_length  petal_width species  sepal_length2
0           5.1          3.5           1.4            1  setosa          26.01
1           4.9          3.0           1.4            1  setosa          24.01
2           4.7          3.2           1.3            1  setosa          22.09
3           4.6          3.1           1.5            1  setosa          21.16
4           5.0          3.6           1.4            1  setosa          25.00
```
#DataFrame.query()によるデータのフィルタリング
eval()と同様に、()内にフィルタリングの条件を文字列で指定します。（つまり""または''で囲む。）

```python
df=sns.load_dataset("iris")#上記の操作でsepal_length2列が追加されてしまったので、dfをもとのデータに直しておきます。
```


```python
df.query("sepal_length>7 & petal_length<6.5") #"かつ"は&で条件をつなげ、"または"は|で条件をつなげます。
```


```python
     sepal_length  sepal_width  petal_length  petal_width    species
102           7.1          3.0           5.9          2.1  virginica
107           7.3          2.9           6.3          1.8  virginica
109           7.2          3.6           6.1          2.5  virginica
125           7.2          3.2           6.0          1.8  virginica
129           7.2          3.0           5.8          1.6  virginica
130           7.4          2.8           6.1          1.9  virginica
131           7.9          3.8           6.4          2.0  virginica
135           7.7          3.0           6.1          2.3  virginica
```

```python
df.query("species=='virginica'").head() #species列のデータが'virginica'に一致するものを抽出
```

```python
     sepal_length  sepal_width  petal_length  petal_width    species
100           6.3          3.3           6.0          2.5  virginica
101           5.8          2.7           5.1          1.9  virginica
102           7.1          3.0           5.9          2.1  virginica
103           6.3          2.9           5.6          1.8  virginica
104           6.5          3.0           5.8          2.2  virginica
```
#eval()およびquery()の()内で変数を用いる場合は @ を使用する
eval()、query()の()の中で変数を用いるときは、その文字が変数であることを明示するために変数の前に ***@*** をつけます。
※Series.eval()によるデータの計算では@は使えません。

```python
a=300
df.eval("sepal_length+@a").head()
```
```python
0    305.1
1    304.9
2    304.7
3    304.6
4    305.0
```
```python
b=7;c=6.5　#（豆知識）;を書くと、2文を1行で書けます。
df.query("sepal_length>@b & petal_length<@c")
```
```python
     sepal_length  sepal_width  petal_length  petal_width    species
102           7.1          3.0           5.9          2.1  virginica
107           7.3          2.9           6.3          1.8  virginica
109           7.2          3.6           6.1          2.5  virginica
125           7.2          3.2           6.0          1.8  virginica
129           7.2          3.0           5.8          1.6  virginica
130           7.4          2.8           6.1          1.9  virginica
131           7.9          3.8           6.4          2.0  virginica
135           7.7          3.0           6.1          2.3  virginica
```


#リスト内包表記による列の追加及び列のデータの更新
リスト内包表記については、以下の記事が参考になると思います。
[pythonの内包表記を少し詳しく](https://qiita.com/y__sama/items/a2c458de97c4aa5a98e7)

リスト内包表記を使うことで、species列の各行の値('setosa','versicolor','virginica')のリストが返されます。これらの値を入力として、'setosa'の場合は1, 'versicolor'の場合は2, 'virginica'の場合は3を返す関数を以下のように定義します。

```python
def species_to_num(species):
    if species=='setosa':
        return 1
    elif species=='versicolor':
        return 2
    elif species=='virginica':
        return 3
```
上記の関数を使用して、結果を'Species_num'列に格納します。

```python
df['Species_num']=[species_to_num(species) for species in df['species']]
```

```python
df.head()#結果の確認
```
```python
   sepal_length  sepal_width     ...       species  Species_num
0           5.1          3.5     ...        setosa            1
1           4.9          3.0     ...        setosa            1
2           4.7          3.2     ...        setosa            1
3           4.6          3.1     ...        setosa            1
4           5.0          3.6     ...        setosa            1
```
ちなみに、species_to_num(species)関数に入力されているリストは以下のように確認できます。


```python
[species for species in df['species']]#species_to_num(species)関数に入力されるリストの確認
```
```python
['setosa',
 'setosa',
 'setosa',
 ~ ~ ~ ~ ~(長いので省略)
 'virginica',
 'virginica',
 'virginica']
```
#DataFrame.map()による列の追加及び列のデータの更新
リスト内包表記を用いずにmap()関数を用いても、同様の処理ができます。
DataFrame.map()関数については、以下のサイトが参考になります。
map()関数に辞書型を入力することで、要素の置換を行えます。replace()を用いて、同様の処理も行えます。以下の記事を参照してみてください。

[pandas.Seriesのmapメソッドで列の要素を置換](https://note.nkmk.me/python-pandas-map-replace/)

まず、置換のための辞書を定義します。

```python
species={'setosa':1,'versicolor':2,'virginica':3}
```
次にmap()関数を使って、結果を'Species_num2'列に格納します。

```python
df['Species_num2']=df['species'].map(species)
```
```python
df.head()#結果の確認
```
```python
   sepal_length  sepal_width      ...       species  Species_num2
0           5.1          3.5      ...        setosa             1
1           4.9          3.0      ...        setosa             1
2           4.7          3.2      ...        setosa             1
3           4.6          3.1      ...        setosa             1
4           5.0          3.6      ...        setosa             1
```
以上です。(2018/01/02)