11
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Python】pandas 再利用しそうなコード

Last updated at Posted at 2019-12-15

インポート

インポート
 
import pandas as pd

ついでに、下記もインポートしておく
(データフレームを表示する際にprintを使うよりdisplayを使うほうがきれい)

from IPython.display import display

データ確認

データ確認
 
# 先頭の5行を表示
print(df.head(5))
# 最後尾の5行を表示
print(df.tail(5))
# dataframe形式の表のレイアウトで表示
display(df)

DataFrame

DataFrame
 

空のデータフレーム

# 空のデータフレーム
df = pd.DataFrame(index=[], columns=[])
df = pd.DataFrame(index=[], columns=range(15))
df = pd.DataFrame(0,index=range(4), columns=range(15))  # 0で埋める

# 既存データフレームから空のデータフレームを作成
df_blank = df.iloc[0:0]

列(Columns)名置き換え

# カラム名を連番に置き換え           (forで加工しやすいので)
df.columns=list(range(len(df.columns)))
# カラム名をアルファベットに置き換え  (Excelと整合しやすいので)
df.columns=([chr(ord('A') + i) for i in range(26)]+["AA"]+["AB"])

行(Index)名振り直し

# indexを0から振り直す
df=df.reset_index()
df=df.reset_index(drop=True)

# indexを1から振り直す                (Excelと整合しやすいので)
df.index = df.index + 1

# indexとは別の行に連番を振る
serial_num = pd.RangeIndex(start=0, stop=len(df.index) , step=1)
df['No'] = serial_num

列(Columns)加工

列加工
 

列抽出

df['A']
df=df[["F","Z"]]
# 任意の列だけ表示
df[['列名']]
# 1,2,4 行目
df.iloc[[1,2,4]]
# 0-2 列目
df.iloc[[0,2]]

列追加

# ない列を指定すると列が追加される
df['job'] = ["Engineer"]
df['new_column'] = 0         #  初期値を0で埋めて追加

条件抽出

df=df[df['A'] > 450]
df=df[df['A']=='P1'] 
# 複数条件指定
【注】(and、or、not)の替わりに(&、|、~)を使わないとエラーとなる
【注】比較演算子を使うときは条件ごとに括弧で囲まないとエラーとなる
df=df[(df['D']==0.0) | (df['D']==0.1)]

条件代入

# x=0 → y  x<>0 →x 
dfsum["z"]=dfsum["y"].where(dfsum["x"] ==0, dfsum["x"])
# 代入
gf2["打率"]=gf2['安打']/gf2['打数']

列名変更

# y を sales に変換
df.rename(columns={'y': 'sales'}, inplace=True)
df.columns = ['year_orig', 'pop', 'rate', '%']

列削除

# 列の場合はaxis=1が必要(デフォルトはaxis=0を行指定)
df.drop(['remarks'], axis=1, inplace=True)
# 列の内容の重複を排除
df=set(df2.A列)

列の値代入・更新

df['A'].apply(lambda x: x * 2)   # =A1*2
df['A'].apply(lambda x: 1 if x>0 else 0)  # IF(A1>0,1,0)的

スライス

# expand=Trueがあると、2つに分割してくれるが、ないとリスト形式内で分割される
print(df['a'].str[:2],expand=True)

タイプ変更

# 最初はobject型になっている
df=df.astype(float)
df1["G"]=df1["G"].astype(int)
オプション 説明
inplace=True 破壊的変更となり、元データも変更になる

行(Index)加工

行加工
 

【注】0から始まるので、Excel行-1となる

行抽出

# 特定の区間の行を抽出する
df[1:3]
#  100の行だけ抽出
df.loc[100]
#  100行目から105行目まで抽出
df[100:106]
# 最初の10行だけ抽出
df[:10]

行追加

ない行を指定すると行が追加される
df.loc['ONE'] = 0
# 行ごとに値追加
df.loc['FIVE'] = ['A5', 'B5', 'C5']

record = pd.Series([VD0,VD1], index=df2.columns)
df2 = df2.append(record, ignore_index=True)

行削除

df=df.drop(range(0,3))
df.drop(range(0,3),inplace=True )

置換

置換
 
df['col1'] = df['col1'].str.replace('x', 'z')

# 複数一括
df['col1']= df['col1'].replace({0:-1,1:-2,2:-3})

結合

結合
 
# 縦結合
df=pd.concat([df, df1])
# 横結合
df=pd.concat([df, df1], axis=1)

【注】Indexが異なると、真横に結合されないので、真横につけたい時はIndexを振り直す

マージ

マージ
 
dfsum=pd.merge(dfsum, gf2,on='キー',how="outer")

・「on」--- 明示的に結合するキーを指定
複数指定可能 on=['keyA', 'keyB']
・how」-- 結合方法を指定
inner -- 両方のデータフレームのキーがあるもののみ
left -- 左のデータフレームに。右のデータフレームの情報が付加され、不足はNaN
right -- 右のデータフレームに。左のデータフレームの情報が付加され、不足はNaN
outer -- 両方のデータフレームのすべてのキーを選択。不足情報はNaN

グループ

グループ
 
gf = df3.groupby('選手名')
gf1=gf.agg({'本塁': max,'盗塁':'max','打率':'max'})

セル

セル
 
# 指定 (atの方が早いらしい)
df.loc[333,'bbb']    #df.loc['行名','列名']
df.iloc[2,1]     #df.iloc['行番号','列番号']
df.at[333,'bbb']    #df.at['行名','列名']
df.iat[2,1]          # df.at['行番号','列番号']
# 代入
df.loc[99,0] ='▲'
df.loc[:, 2:8] = 0

【注】df.loc[99][0]の書き方(chained indexing)だと、SettingWithCopyWarningが発生したり、
値がかわらなかったりする

# 値の条件抽出
VD0=df1.loc[((df1["D"]==0) & (df1["G"]==6)),"E"] 
VD0=VD0.values.tolist()[0]    

ソート

ソート
 
df.sort_values(['sales', 'temperature'], ascending=False)
sorted(df)
オプション 説明
ascending=True 降順
ascending=False 昇順

複製

複製
 
df1 = df.copy() 

【注】df1 = dfにすると、参照渡しになるので、df1を変更するとdfも変わってしまう

変換

変換
 
# リスト → DataFrame
pd.DataFrame(data=list)

# データ部分 → リスト
s = pd.Series([0, 1, 2])
print(s)
#  0    0
#  1    1
#  2    2
#  dtype: int64
list= s.values.tolist()    # リストになる
V0=s.values.tolist()[0]    # 値取出し

表示

表示
 
# カラム、Indexを表示しない
print(df.to_string(index=False, header=False))

既存のデータフレームを新しいデータフレーム分を更新する

既存のデータフレームを更新
 

(条件)
・既存データフレーム
 NaNがある
 新データフレームにない列がある
 新データフレームにない行がある
・新しいデータフレーム
 NaNがある
 既存データフレームにない列がある
 既存データフレームにない行がある
・更新条件
 数字は大きい方を採用
 文字は新しい方を採用
(結果)
いい方法が、見つからず。
下記のように、しましたが、いい方法がありましたら、御教授をお願いします
(手順)
・マージした後、ソートする
 →これで行数、列数は自動調整される。但し、共通の列は2列にわかれたまま
 df=pd.merge(dfA, dfB,on='A列',how="outer")
 df=df.sort_values(['A列'], ascending=True)
・NaNを一旦、使用していない0に変換する
 df1=df.fillna(0)
・数字のB列は、大きい値を採用
 df1['B列'] = np.where(df1['B列_x']>df1['B列_y'], df1['B列_x'], df1['B列_y'])
・文字列のC列は新しい方を採用する
 単純に上書きすると、既にある値をNaNにしてしまう可能性があるので、NaN=0でない場合のみ書き換える
 df1['C列'] = np.where(df1['C列_y']!=0, df1['C列_y'], df1['C列_x'])
・列を元に戻す
 df2=df1.reindex(columns=['A列', 'B列', 'C列', 'D列', 'E列'])
・0をNaNに戻す
 df2 = df2.replace([0], np.nan)

別ファイルの列同士では、キーが合っていないので、一括では比較できない、そこで最初にマージして
キーを合わすことで、比較できようにした

ファイル読み込み・書き出し

ファイル読み込み・書き出し
 

Excelファイル読み込み

df = pd.read_excel('sample.xlsx',sheet_name='sheet1')
オプション 説明
sheet_name="" シート名を指定
header=None 指定するとヘッダなしで読み込む
指定しないときは、1行目が自動的にカラム名として挿入される
header=2 指定行をヘッダとして読み込み。それ以前の行は無視される。これ以降から0行が始まる

Excelファイル書き出し

df.to_excel('sample.xlsx',sheet_name='sheet1', encoding='cp932',index=False, header=False)
オプション 説明
sheet_name="" シート名を指定
index=False 行名を削除して書き出し
header=False 列名を削除して書き出し

csvファイル読み込み

df=pd.read_csv("sample.csv",encoding="cp932",header=None)
df=pd.read_csv("sample.csv",encoding="shift_jis",header=False)

df1=pd.read_csv(sample.csv,encoding='cp932',names=col_names,low_memory=False )

【注】windows拡張文字列が混ざっている場合は、文字コードをcp932としてやる必要がある
【注】重たいファイル読み込む時はlow_memory=Falseを記載する

df = pd.DataFrame(index=[], columns=range(21))
col_names = ['c{0:02d}'.format(i) for i in range(21)]
df=pd.read_csv("myfile.csv",encoding="cp932", names = col_names)

【注】途中で列数が変わる場合、エラーになるので、事前に列数と仮の名前を設定しておく

csvファイル書き出し

df.to_csv('sample.csv',encoding='cp932',header=False)

TAB区切りファイル読み込み

df=pd.read_csv("sample.DAT",encoding='cp932', sep='\t',names=col_names)

テキストファイル読み込み

df=pd.read_table("sample.DAT",encoding='cp932',header=None)

テキストファイル書き込み

df.to_csv("employee.csv", sep=",",header=False)

欠如データ

欠如データ
 
# A列にあるNaNを'0.0'に置き換える
df.fillna(value={'A': 0.0}, inplace=True)
# A列にNaNがある行を削除する
df.dropna(subset=[A], axis=0, inplace=True)
# A列の '--' を 0に置き換える
df['A'] = df['A'].replace('--', 0).astype(float)

# NaNを上セルの値で埋める
df=df.fillna(method='ffill')

# 0をNaNに戻す
df = df.replace([0], np.nan)

可視化

可視化
 
import matplotlib.pyplot as plt

以下を実行するとプロットスタイルが変更されていい感じになる

plt.style.use('ggplot') 
記法 操作の内容
plt.title('グラフタイトル') タイトルを設定
plt.xlabel('X軸ラベル') x軸の名前を設定
plt.ylabel('Y軸ラベル') y軸の名前を設定
plt.xlim(Xの最小値, Xの最大値) x軸の範囲を指定
plt.ylim(Yの最小値, Yの最大値) y軸の範囲を指定
plt.legend() 凡例を表示
plt.grid() グリッド線を表示
import random
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame(index=[], columns=range(2))
df.columns=list(range(len(df.columns)))

for i in range(4):
    df.loc[i] = [i ,2*random.random()]

print(df)
plt.plot(df[0],df[1])
plt.show()

メモリ節約

メモリ節約

不要な変数を削除して、メモリ解放する

delで不要な変数を削除する

del 変数

使用していないメモリを開放する

gc.collect()

不要なカラムを消す

del df['column1']
# または
df = df.drop(columns=['column1'], axis=1)

read_csvする場合は、必要なカラムだけを読み込む

df = pd.read_csv('file.csv', usecols=['column1', 'column2'])

必要レコードだけ抽出する

df = df.loc[df["id"] >= 100000]

copyの多用しない

df1 = df.copy()  # copyした変数分のメモリが新規に消費されてしまう
df2 = df      # 参照渡ししても問題ない場合はcopy()を使わない

破壊的代入する

既存の変数を変更する際、変数名を変えてしまうと、新しい変数ができてしまうので、
極力同じ変数名を使うようにします。

# 非破壊的な例
df3 = df1.loc[df1['id'] >= 10000]
df4 = pd.concat([df3, df2])

# 破壊的な例
df1 = df1.loc[df1['id'] >= 10000]
df1 = pd.concat([df1, df2])

mergeする際は、copy=Falseにする。

デフォルトだとTrueになっており、copyが生成され、メモリを必要以上に使用してしまう

df1 = df1.merge(df2, on='column1', how='left', copy=False)

カラムの型を指定

指定しないと自動でint64またはfloat64となってしまうので、必要分だけを指定する

df = df.astype(
            {
                "id": np.int32,
                "status": np.int8,
                "price": np.int32,
                "weight": np.float32
            }
        )

read_csvする場合は、読み込み時点で型指定しておく

df = pd.read_csv(
	"file.csv", 
	dtype={
                "id": np.int32,
                "status": np.int8,
                "price": np.int32,
                "weight": np.float32
            }
    )

メモリ使用量の確認方法

print(f"df memory usage: {df.memory_usage(deep=True).sum() / 1024 ** 2} MB")
11
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?