python 自分用メモr5 pandas

##実行環境

* MacBook Air (11-inch, Mid 2012)
* JupyterLab (from Anaconda)
* Python 3.6.4


##教材元
https://www.udemy.com/the-python-mega-course/learn/v4/content

##まえがき
pandasというライブラリーを使ってみるの回。
pandasを使うとcsv,json,xlsxファイルなどをきれいな表で表示することができる。もちろん編集もできる。
jupyterLabかjupyternotebookだときれいに表示される。anacondaには初期からプリインストールされる。

##Pandas

##dataframe

```py

import pandas

a = [[1,2,3],[2,4,6]]
df1 = pandas.DataFrame(a)#1

df1 = pandas.DataFrame(a, columns=["First", "Second","Third"],index=["index0","index1"])#2

type(df1)#3
print(df1.mean())#4
print(df1.First.mean())#5
```
1. df1をprint()すればきれいなグラフが作れる。aに二次元のリスト。a[0],a[1]がrowになる。a[0],a[1]の中身がcolumnとして振り分けられる。
2. columnとrowに名前を割り振ることができる。rowの数、columnの数と同じ量指定しなければならない。データが増えるほどrowの指定は基本されない
3. `pandas.core.frame.DataFrame`オブジェクト
4. メソッドの一例。`mean()`はcolumn全体の平均値を出してくれる
5. columnを指定してメソッドを適用させることもできる。この場合1.5が返る。(1+2)/2の計算結果

```py
df2 = pandas.DataFrame([{"FirstName":"J"},{"LastName":"K"},{"FirstName":"Oppai"}])
```
1. 通常じゃない方法だが、`dcit`型のkeyをcolumn名として指定することもできる。keyの数だけcolumnが増える。column名は一意的なので同じ文字列かつデータ型を重複して持たない。
2. 表がないので見にくいが指定されなかったrowのcolumnには`NaN`のNoneが入る

##csv, json, xlsxを読み込む


```py

import pandas
#csv
df_csv = pandas.read_csv("supermarkets.csv")
#csvその2
df_csv2 = pandas.read_csv("supermarkets-semi-colons.txt",sep=";")
#json
df_json=pandas.read_json("supermarkets.json")
#xlsx
df_xlsx=pandas.read_excel("supermarkets.xlsx")
#web
df_csv3=pandas.read_csv("http://pythonhow.com/supermarkets.csv")

dir(df_csv)
import os
os.listdir()
df_csv.set_index("ID", append=True)
df_csv.shape

```
1. csv, json, xlsxファイルを読み込むのに対応したメソッドが存在する
2. `,`以外で区切られたcsvファイルも読み込むことができる。`sep`引数を指定すればいい。
3. webのurlから直接指定することもできる。
4. 寄り道。`dir()`メソッド内部にobjectを入れれば、インスタンス変数やメソッドを確認することができる
5. `os.listdir()`で作業用ディレクトリーの一覧をリストの形式で取得できる。`glob2`ライブラリーを使いより柔軟に取得することもできる。
6. `df.set_index("column_name")`でグラフのrow_nameをcolumnの値に置き換えることができる。juypiterlabで動かすと一目瞭然。inplaceメソッドではない。`inplace=True`にして直接変更を加えることもできる。juypiterlabのshift+tabは神
7. `shape`でDataFrameの(index数, columnの数)というintの要素を含むtupleが返される。


##DataFrameの削除、追加、編集
###スライス
```py
import pandas
df = pandas.read_csv("http://pythonhow.com/supermarkets.csv")
#location
df.loc[1:3, "State":"Name]
df.loc[:2,]

#integer location
df.iloc[2:4,1:5]
df.iloc[3,4]

#column, index
df.columns
df.columns[2:5]
df.index
df.index[3:]

df.Country
df.Name
df.City

```
1. `loc`は表をリストのようにスライスできる。df.loc[index範囲,column範囲]の形式。リストの実際のスライスと違って[start:end]の場合endを含んで形式で返す。
2. `iloc`で実際のリストと同じ感覚でスライスできる。[start:end]のendの要素はリストと同様に含まれない。
3. `dir(対象のDataFrame)`を使えば変数の確認ができる。`df.columns`はデータフレイムのcolumnの列の各値をリストのような形式で返す(表の一番上の部分)。`df.index`は上から順番にrowの要素をリストのような形式で返す。スライスできる
4. `df.columns`の中にあるcolumn名を使い、`df.column_name`をすれば対象columnの値全てをリストのような形式で返す。スライスもできる

###削除
```py
import pandas
df = pandas.read_csv("http://pythonhow.com/supermarkets.csv")
df.drop(1, 0)
df.drop("Country",1)
```
1. `drop()`で削除できる。inplaceメソッドではないので、別の変数に格納する必要がある。1つめの引数はindexの値(intか、set_index("column_name")でkewwardが担っている場合もあるため)か、あるいはcolumn名である。2つ目の引数は0か1。0ならばrowを表す。1ならばcolumnを表す。そして指定されたrowかcolumnをまるごと削除する。
2. スライスでも擬似削除ができる

###追加
```py
df["New"]="test"
df["New2"]=df["Name"]+","+df["Country"]
```

1. "test"だとこの新しいNewのcolumnの値は、全rowで"test"になる
2. 辞書のように追加できる。`df["new_column_name"]=value`。list型で追加する場合は、rowの長さと同等である必要がある。
3. `df["Name"]+","+df["Country"]`。都合がいいことに同じrowの他のcolumnの値を取得して、値を作ることもできる。



###座標
```py
a=df["Name"][1]
b=df.Name[1]
```
1. DataFrame、表の特定の1座標の値を取得する方法。aとbは等価である。
2. aの方法の場合、`df[column_name][row_name]となる。row_nameはrowの最も左側にあるvalueを指す。グラフがないと直感的じゃない。jupyterlabで見ることを推奨。
3. bの場合、`df.Name`のリストのindex[1]番目となる。
4. 特定の座標に別の値を代入する場合は`df.["column_name"][row_name]=value`とすればいい。`df.column_name[index]=value`でも変わる


###置き換え
```py
df_t=df.T
```
1. rowとcolumnの位置関係を置き換えることができる。jupyterlabで確認推奨
2. 新しいrowを追加したい場合は、`df.T`から前述の新しいcolumnを追加する。と同じ操作を行う。valueがリストの形式ならば、columnの種類数と同じ長さのリストである必要がある


##geopy.geocodersで遊ぶ

```py
from geopy.geocoders import Nominatim
nom = Nominatim(scheme="http")

n = nom.geocode("3395 23rd st, San Francisco, CA 94114")
print(n)
>>>Location(23rd Street, Potrero Terrace, SF, California, 94114, United States of America, (37.7544336, -122.4040117, 0.0))
type(n)
>>>geopy.location.Location
print(n.latitude)#緯度
>>>37.7544336
print(n.longitude)#経度
>>>-122.4040117


#latitude, longtitudeのカラムを作る
import pandas
df = pandas.read_csv("supermarkets.csv")
df["New_address"]=df["Address"]+","+df["City"]+","+df["State"]+","+df["Country"]
df["Coordinate"] = df["New_address"].apply(nom.geocode)
df["Latitude"]=df.Coordinates.apply(lambda x:x.latitude if x!=None else None)
df["longtitude"]=df.Coordinates.apply(lambda x:x.longtitude if x!= None else None)

```
1. 住所を`geocode()`に投げると`geopy.location.Location`objectを返してくれる。簡単にいうと、緯度と経度を取得できる。web接続して、対応した座標を返してくれるメソッド。
2. なんか連続して実行すると、わけわかめなエラーはく。ちょっと時間おく必要ある。

pandasへ
1. "New_address"というコラムを作った。値はそれぞれ同じrowから取得して、","で結合させた
2. `apply()`メソッドを使うと、iterateせずにrow数だけ関数を適用して、新しい値を作ることできる。"New_address"にたいして、`nom.geocode`を適用した。
3. "Latitude"と"Longtitude"のカラムを作る。df["Coordinates"]の各値は`geopy.location.Location`だからインスタンス変数を直接していすればいいじゃない？と思うが無理。df["Coordinates"]自体は`pandas.core.series.Series`objectである。各rowごとにそれぞれの`geopy.location.Location`を取り出さないといけない。だから`apply()`を使っている。


##あとがき
あそびあそばせとはたらく細胞アニメ化めでてぇ