Python

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

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

csv, json, xlsxを読み込む

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の削除、追加、編集

スライス

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の値全てをリストのような形式で返す。スライスもできる

削除

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. スライスでも擬似削除ができる

追加

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の値を取得して、値を作ることもできる。

座標

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でも変わる

置き換え

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

geopy.geocodersで遊ぶ

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.Locationobjectを返してくれる。簡単にいうと、緯度と経度を取得できる。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.Seriesobjectである。各rowごとにそれぞれのgeopy.location.Locationを取り出さないといけない。だからapply()を使っている。

あとがき

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