pandasでよく使う操作

時系列データの扱い
resample

1. データフレームの作成
1-1. DataFrameの作成
Dictionaryを渡すことでDataFrameが自分で作成できる
# Pre-defined lists
names = ['United States', 'Australia', 'Japan', 'India', 'Russia', 'Morocco', 'Egypt']
dr = [True, False, False, False, True, True, True]
cpc = [809, 731, 588, 18, 200, 70, 45]
# Import pandas as pd
import pandas as pd
# Create dictionary my_dict with three key:value pairs: my_dict
my_dict = {
'country': names,
'drive_right': dr,
'car_per_cap': cpc
}
# Build a DataFrame cars from my_dict: cars
cars = pd.DataFrame(my_dict)
インデックスの設定
インデックスを指定しなければ0からの番号が自動で設定される。
後からインデックスを設定するには.index
に対応するlabelを代入すればOK
# Definition of row_labels
row_labels = ['US', 'AUS', 'JPN', 'IN', 'RU', 'MOR', 'EG']
# Specify row labels of cars
cars.index = row_labels
以下のように作成時にインデックスを指定することも可能。
scores_df = pd.DataFrame({'点数': scores},
index=pd.Index(['A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J'],
name='生徒'))
列と行に名前の設定
indexとcolumnsそれぞれにname
を設定することができる。
(groupbyやpivot_tableのときに設定されているやつ?)
frame3.index.name = 'year'; frame3.columns.name = 'state'
frame3
>>>
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
1-2. ファイルからの読み込み
ユースケース
同じレイアウトのファイルを複数読み込む場合
主にDB等外部のソースからデータ量が多すぎて複数のファイルに分割した場合を想定
df_list = []
for filename in tqdm(["[JST_OrderManagement_His1].rpt.pkl.gz",
"[JST_OrderManagement_His2].rpt.pkl.gz",
"[JST_OrderManagement_His3].rpt.pkl.gz"]):
df = pd.read_pickle("../data/raw/pkl/" + filename)
df_list.append(df[:-1])
JST_OrderManagement_His_df = pd.concat(df_list,
axis=0,
ignore_index=True)
CSV
pd.read_csv
で読み込める
# Fix import by including index_col
cars = pd.read_csv('cars.csv')
- インデックスの指定
上記のようにインデックスがずれてしまう時はファイルのどの項目をインデックスにするかindex_col
で指定ができる。指定には数字だけでなく項目名(ヘッダー名)で指定することもできる。
特に日付(DatetimeIndex)を指定したい時に便利?
# Fix import by including index_col
cars = pd.read_csv('cars.csv', index_col=0)
# index_colを指定
medal_df = pd.read_csv(file_name, header=0, index_col='Country', names=columns)
- 項目名の指定
names=('A', 'B', 'C', 'D')のように任意の値を列名として設定することもできる。リストやタプルで指定する。
Pickleの読み込み
- pickleは
read_pickle
で読み込みができる(.gzでも可)
df_list = []
for filename in tqdm(["[JST_OrderManagement_His1].rpt.pkl.gz",
"[JST_OrderManagement_His2].rpt.pkl.gz",
"[JST_OrderManagement_His3].rpt.pkl.gz"]):
df = pd.read_pickle("../data/raw/pkl/" + filename)
df_list.append(df[:-1])
JST_OrderManagement_His_df = pd.concat(df_list,
axis=0,
ignore_index=True)
Excelの読み込み
エクセルを読み込む(DataFrameに変換する)には以下2つの方法がある
- ExcelFile.parse
- read_excel
ExcelFile.parseだとエクセルのシートそのものが初回時にのみ読み込まれるが、read_excelを使うと引数に指定するのは対象ファイルのパスであるが、read_excelを使う都度にファイルの読み込みが発生するため、対象ファイルにシートがたくさんあったり、行数が多かったりするとパフォーマンスが低下する
stackoverflow - ExcelFile Vs. read_excel in pandas
ExcelFile
xlrdが必要なので、事前にインストールする。ないと以下のエラーが出る
ImportError: Missing optional dependency 'xlrd'. Install xlrd >= 1.0.0 for Excel support Use pip or conda to install xlrd.
# Excelファイルを読み込む
xls = pd.ExcelFile('data/' + FILE_NAME)
# 取り込み対象から除外できるデータがないかデータを見て確認する
# skiprows:先頭の何行を読み込まないかを指定する引数
# skip_footer:最後の何行を読み込まないか指定する引数
# usecols:読み込む列を指定
df = xls.parse('二人',
skiprows = 10,
skip_footer = 2,
usecols = "H:CG")

2. Pandasの基本(Essential Functionality)
2-1. インデックス、項目名の操作
reindex
-
reindex
で指定したインデックスを元に新しいobjectを作成できる。
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
obj2
>>>
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
rename
rename
でインデックスを新しく振り直せる
order.rename(index=order['TARGET_DATE'])
以下のように列名を変更するのにも使える
df.rename(columns={ 0: 'monthly'})
-
reset_index
- インデックスの値を解除して、0からの通番をインデックスにする
-
set_index
- 指定した項目をインデックスにする
pandas.DataFrame, Seriesのインデックスを振り直すreset_index
reset_index
f
dropオプションを設定しないと元々あったインデックスが項目として設定される。drop
にTrueを設定するとインデックスがそのままになる。
> print(cars.reset_index())
index country drive_right car_per_cap
0 0 United States True 809
1 1 Australia False 731
2 2 Japan False 588
3 3 India False 18
4 4 Russia True 200
5 5 Morocco True 70
6 6 Egypt True 45
> print(cars.reset_index(drop=True))
country drive_right car_per_cap
0 United States True 809
1 Australia False 731
2 Japan False 588
3 India False 18
4 Russia True 200
5 Morocco True 70
6 Egypt True 45
以下のようにソートしたときにはインデックスをリセットするとソート後の結果でインデックスの数字をふる事ができる。
cars.sort_values(['car_per_cap']).reset_index(drop=True)
country drive_right car_per_cap
0 India False 18
1 Egypt True 45
2 Morocco True 70
3 Russia True 200
4 Japan False 588
5 Australia False 731
6 United States True 809
ソート
sort_values
で項目を指定してソートができる。
複数の項目を指定することもできる
# 項目を指定してソート
df.sort_values(by=["項目1"], ascending=True)
# 項目1を昇順、項目2を降順
df.sort_values(by=["項目1", "項目2"], ascending=[True,False])
以下のようにlocで要素を指定するとキーを指定して並べ替えることもできる。
result.loc[ ['[18, 31)', '[31, 42)', '[42, 53)', '[53, 64)', '[64, 75)', '75+']]
daily weekly monthly
age_group
[18, 31) 2.59 2.89 3.21
[31, 42) 12.11 12.92 13.72
[42, 53) 24.42 24.38 24.81
[53, 64) 25.29 25.01 24.84
[64, 75) 27.48 26.94 26.05
75+ 8.11 7.86 7.37
また、項目で並び替えを行うときには以下のようにcolumns
で指定すればOK
pd.DataFrame(data, columns=['year', 'state', 'pop'])
結合、連結
- merge
- 項目での結合もできる
- joinより細かな指定ができる
- 一度に結合できるのは2つまで
- join
- デフォルトでインデックス同士の連結
- 複数のDataFrameを連結できる
# left_on, right_onでそれぞれのデータフレームの列名を指定する
pd.merge(df_ab, df_ac_, left_on='a', right_on='a_')

3. データフレームからのデータ抽出
アクセス方法は大きく分けて以下の3種類
- Slicing
- An individual index (through the functions iloc or loc)
- Boolean indexing
Slicing
一番シンプルな方法。
# 項目名を指定して対象項目のみを抽出(以下2つは同じ結果になる)
>>>df['name']
>>>df.name
# 複数の列にアクセスするには列の名前のリストを渡す
>>>df[['name', 'age']]
# locを使っても大丈夫
>>>df.loc[:, ['name', 'age']]
# 条件を複数指定したいときはisinを使う
df[df['city'].isin(['Tokyo', 'Osaka']]
# 表全体ではなく、特定の列からサブセットを取り出すこともできる(生存者のうち年齢が30以上)
df['survived'][df['age'] >= 30]
また、指定にあたっては[]
を重ねるとDataFrameの形式で抽出できる。
# Print out country column as Pandas Series
print(type(cars['country']))
# Print out country column as Pandas DataFrame
print(type(cars[['country']]))
[]
でインデックスの開始と終了を指定することで行を指定してセレクトもできる。
# Print out first 3 observations
print(cars[0:3])
# Print out fourth, fifth and sixth observation
print(cars[3:6])
An individual index(loc, ilic)
Slicingだけだと機能には限りがあり、numpyの2d-arrayのようにarray[rows, columns]
の形でデータを抽出するにはlocやilocを使う必要がある
- loc(label-based)
- iloc(integer position-based)
locとilocは指定方法がラベル名かインデックスかの違いで実現できる結果は同じ。
以下の例ではlocとilocで返される結果は同じになる。
# Seriesを抽出
cars.loc['RU']
cars.iloc[4]
# DataFrameを抽出
cars.loc[['RU']]
cars.iloc[[4]]
# DataFrameで複数の項目を抽出
cars.loc[['RU', 'AUS']]
cars.iloc[[4, 1]]
また、以下のようにインデックスと項目の両方を指定することもできる。
# rowとcolumnの両方を指定して1つの項目を抽出
cars.loc['IN', 'cars_per_cap']
cars.iloc[3, 0]
# 複数のrowと一つのcolumnを指定
cars.loc[['IN', 'RU'], 'cars_per_cap']
cars.iloc[[3, 4], 0]
# 複数のrowと複数のcolumnを指定
cars.loc[['IN', 'RU'], ['cars_per_cap', 'country']]
cars.iloc[[3, 4], [0, 1]]
項目を指定してセレクト
locとilocで項目を指定して全ての行をセレクトすることもできる(インデックスでの項目指定と同じように)
# 項目を指定して全ての行をSereisでセレクト
cars.loc[:, 'country']
cars.iloc[:, 1]
# 複数の項目を指定して全ての行をDataFrameでセレクト
cars.loc[:, ['country','drives_right']]
cars.iloc[:, [1, 2]]
Boolean Indexing
- 複数条件を組み合わせる場合には
()
が必要な点に注意
# trueとfalseのステートメントを使ってサブセットを取り出せる
df[df['age'] >= 30]
df[df['city'] == 'Tokyo']
# 応用例。booleanのSeriesを作って、条件を満たすデータからソート。
atleast_100 = movie_stats['rating']['size'] >= 100
movie_stats[atleast_100].sort_values(by=[('rating', 'mean')],
ascending=False)[:15]
>>>football[(football.wins > 10) & (football.team == "Packers")]
losses team wins year
3 1 Packers 15 2011
4 5 Packers 11 2012
その他ユースケース
nullが入っているデータ
isnull
でnullが含まれているデータを検索できる
# nullの判定を実施
df['SAMPLE'].isnull()
# nullの行だけを抽出
df[df['SAMPLE'].isnull()]
条件検索で複数の条件のどれかに合致
以下のようにisin
を利用することでListの中の項目に一致するデータを抽出できる
(df[df['state'].isin(['NY', 'TX'])])
より高度な検索機能
# 条件の中で変数を使う
val = 80
df.query('point > @val')
# 複数条件を指定
df.query('age < 25 & point > 65')
df.query('age < 25 and point > 65')

4. データの削除、欠損値
-
drop
で削除する -
axis=1
で列の削除であることを明示する
order_ts_dropped = order_ts.drop("TARGET_DATE", axis=1)
欠損値の扱い
# NaNが1つでもある行を削除
df.dropna()
# 全ての列がNaNの行を削除
df.dropna(how='all')
# 項目を指定して対象項目がNaNの場合のみ除外
df.dropna(subset=['CHANNEL_KBN'])

5. データの追加、変換
データの追加
新しい列名を指定することで項目を追加できる。
# Add total col as sum of individuals and family_members
homelessness['total'] = homelessness['individuals'] + homelessness['family_members']
# Add p_individuals col as proportion of individuals
homelessness['p_individuals'] = homelessness['individuals'] / homelessness['total']
# See the result
print(homelessness)
データタイプの変更
- astypeでデータの変換が行える
s_f = s.astype('float64')
print(s_f)
# 0 13.0
# 1 23.0
# 2 33.0
# Name: c, dtype: float64
print(s)
# 0 13
# 1 23
# 2 33
# Name: c, dtype: int64
pandasのデータ型dtype一覧とastypeによる変換(キャスト)
条件分岐、ループ
- forループと
iterrows()
を組み合わせることでDataFrameをループさせられる- 1つ目でラベル(インデックス)、2つ目で行全体にアクセスできる
- ただし、iterationのたびに新しいSeriesを作ることになるので非効率
# Iterate over rows of cars
for lab, row in cars.iterrows():
print(lab)
print(row)
>>>
US
cars_per_cap 809
country United States
drives_right True
Name: US, dtype: object
# iterrowsを使って新しい項目を作ることもできる
# Code for loop that adds COUNTRY column
for lab, row in cars.iterrows() :
cars.loc[lab, 'COUNTRY'] = row["country"].upper()
-
apply
を使うことで行ごとに同じ関数を適用できる
pandasで条件分岐(case when的な)によるデータ加工を網羅したい
pandasで複数カラムをfor文で処理するときの高速化Tips
うわっ…私のpandas、遅すぎ…?って時にやるべきこと(先人の知恵より)****
1つの項目がインプット
1つの項目が対象であれば単純にapplyを実行すればOK。
# Responseという項目について、値がNoなら0、それ以外なら1を設定した項目を追加
df['Engaged'] = df['Response'].apply(lambda x: 0 if x == 'No' else 1)
上記の応用例でage
という項目の値に応じてグループのラベルをつける例
df['age_group'] = df['age'].apply(
lambda x: '[18, 30)' if x < 30 else '[30, 40)' if x < 40 \
else '[40, 50)' if x < 50 else '[50, 60)' if x < 60 \
else '[60, 70)' if x < 70 else '70+'
)
条件が細かくなるならlambdaではなく関数を定義してもOK
def func_cate(x):
if x < 10000:
return 0
elif x >= 10000 and x < 15000:
return 1
elif x >= 15000 and x < 19500:
return 2
else:
return 3
stocks['cate'] = stocks['open'].apply(func_cate)
2つ以上の項目がインプット
DataFrameに対して処理を行い、尚且つapplyでaxis=1
を指定する事で行を引数として渡す
def func_cate_change(x):
if x.open < x.close:
return 1
elif x.open > x.close:
return 2
else:
return 0
stocks['cate_change'] = stocks.apply(lambda x:func_cate_change(x),axis=1)
2つ以上の項目がインプットで高速に処理
pandasで複数カラムを参照して高速に1行1行値を調整する際のメモ
Categorical Dataの変換
- Factorize
- Categorical
Factorize
SeriesのFactorizeメソッドを使ってCategoricalデータの変換を行える。
ただし、数値の順序は指定できないので、順序が意味を持つケースでは使用できない。
gender_values, gender_labels = df['Gender'].factorize()
gender_values # array([0, 0, 0, ..., 1, 1, 1])
gender_labels # Index(['F', 'M'], dtype='object')
Categorical
pandasのCategoricalクラスを使えば順序を考慮してCategoricalデータを数値に変換できる
categories = pd.Categorical(
df['Education'],
categories=['High School or Below', 'Bachelor', 'College', 'Master', 'Doctor']
)
日付の取り扱い
以下のようにto_datetime
でフォーマットを指定してSeriesをまとめてdatetimeに変換できる
sales['pd_date'] = pd.to_datetime(sales['date2'], format='%m/%d/%Y')

6. データの集計
集計関数(sum, count等)
sum
やcount
等の集計関数を使ってDataFrameやSeriesの結果を集計できる。
引数でaxis
の指定を行うことで集計対象を列か行か指定できる(axis=0(デフォルト)で列、axis=1で行)
> order_by_week.sum()
loginID
00076289 1473.0
0011C8B3 2.0
0013AF4C 13.0
0017472F 12.0
001D1FC7 229.0
> order_by_week.sum(axis=1)
TARGET_DATE
2020-03-11 269191.0
2020-03-18 211634.0
2020-03-25 275430.0
2020-04-01 252704.0
2020-04-08 243389.0
pandasで特定の条件を満たす要素数をカウント(全体、行・列ごと)
割合の算出
データフレームの値を割合に変更したいときはapply
を使って計算することができる
df_percent = temp_df.iloc[:, [0,1]].apply(lambda x: round(x / x.sum() * 100, 2), axis = 1)
分析
ユニークなデータ数(ユーザの数とか)
unique
の結果をshapeで表示することで分かる
JST_OrderManagement_His_df["loginID"].unique().shape
GROUP BY
ユーザごとの平均値など、グループ化した結果を取得したい時にはgroup byを使う。
# ユーザごとの平均評価点を求める
lens.groupby('user_id').mean()
# 映画ごとの平均評価点を求める
lens.groupby('movie_id').mean()
# ユーザごとに通番の番号をふる(0から始まるので+1する)
lens.groupby('user_id').cumcount()+1
# 全体に同じ関数を適用
>>> df.groupby('city').agg(np.mean)
price quantity
city
osaka 212.5 2.5
tokyo 250.0 6.0
# グループごとに適用する関数を指定
>>> df.groupby('city').agg({'price': np.mean, 'quantity': np.sum})
price quantity
city
osaka 212.5 10
tokyo 250.0 18
# 同じグループに複数の関数を指定
>>> movie_stats = lens.groupby('title').agg({'rating': [np.size, np.mean]})
rating
size mean
title
'Til There Was You (1997) 9 2.333333
1-900 (1994) 5 2.600000
GroupByの流れ
- groupbyの結果にはどんなメソッドでも渡せる
- 渡したらそれがgroupbyの結果の各グループに適用される
decade = 10 * (planets['year'] // 10)
decade = decade.astype(str) + 's'
decade.name = 'decade'
planets.groupby(['method', decade])['number'].sum().unstack().fillna(0)
aggregate
filter
Groupbyとunstackの組み合わせ
unstackを活用することで行と列それぞれの対応関係を持つDataTableを簡単に作れる。
そのまま描画ができるので非常に便利。
age_marital_df = df.groupby(['age_group', 'marital'])['conversion'].sum().unstack('marital').fillna(0)
age_marital_df = age_marital_df.divide(
df.groupby(
by='age_group'
)['conversion'].count(),
axis=0
)
Groupbyの結果を条件指定
groupbyした結果を条件つきカウントするには以下の方法でOK
df11=df.groupby('key1')['key2'].apply(lambda x: (x=='one').sum()).reset_index(name='count')
Pandas Dataframeでgroupbyの後に条件付きカウントを行う方法は?
Grouper
Grouperを使うことでpivot_tableやgroupbyを期間ごとの集計と組み合わせることができる
Python pandas アクセサ / Grouperで少し高度なグルーピング/集計
Pivot Table
多次元のgroup byと捉えればOK?
# groupby
titanic.groupby(['sex', 'class'])['survived'].aggregate('mean').unstack()
# pivot_table
titanic.pivot_table('survived', index='sex', columns='class')
以下のようにcutと組み合わせて分類した結果を項目にすることもできる
(第一引数が対象の項目、第二引数がインデックス、第三引数が項目?)
age = pd.cut(titanic['age'], [0, 18, 80])
titanic.pivot_table('survived', ['sex', age], 'class')
aggfunc
aggfuncでaggregationを実施する方法を指定できる(デフォルトはmean)
以下のように複数の項目を指定して、項目ごとに異なる集計を行うことも可能。
titanic.pivot_table(index='sex', columns='class',
aggfunc={'survived':sum, 'fare': 'mean'})
margins
margins=Trueを設定することで総計を表示することができる
titanic.pivot_table('survived', index='sex', columns='class', margins=True)
割合での表示

7. 時系列データ(Time-Series)
Datetimeの活用
- Indexing by Time
Datetimeをindexに設定すると以下のようにslicingで条件を指定できる他、resemple
やGrouper
等、時系列分析に便利な関数が利用できる
index = pd.DatetimeIndex(['2014-07-04', '2014-08-04',
'2015-07-04', '2015-08-04'])
data = pd.Series([0, 1, 2, 3], index=index)
data['2014-07-04':'2015-07-04']
上記はDataFrame作成時に設定したが、既存の項目をインデックスに設定するにはrenameを利用すればOK。
order['TARGET_DATE'] = pd.to_datetime(order['TARGET_DATE'], format='%Y/%m/%d')
order_ts = order.rename(index=order['TARGET_DATE'])
日付で期間等を指定するにはdatetimeに変換してから抽出をすればOK
df['RecordDate_dt'] = pd.to_datetime(df['RecordDate'], format='%Y%m%d')
start = 20200311
end = 20200609
df.query('RecordDate_dt >= @start & RecordDate_dt <= @end')
上記でも意図した結果になると思われるが、datetime型で比較を行ったほうが良い?
df1[(df1['日付'] >= dt.datetime(2019,5,3)) & (df1['日付'] < dt.datetime(2019,5,6))]
年や月等の値へのアクセス
datetimeのデータの一部分にdataframe["column"].dt.component
の形式でアクセスできる。
componentはyear
やmonth
のこと。
# 年にアクセス
df['date'].dt.year
# 月にアクセス
df['date'].dt.month
# 日付
df['InvoiceDate'].dt.date
pandasのDataFrameから期間を範囲指定して抽出する
resampleを利用した一定期間ごとの集計
以下のように時間をインデックスにしたDataframeはresample
で特定の期間ごとの値を集計できる
uri_df.iplot(title="注文金額推移(売り)")
kai_df.iplot(title="注文金額推移(買い)")
# 日次, 週次, 月次ごとの注文金額合計と注文頻度の推移
for symbol, name in zip(["D", "W", "M"],
["日次", "週次", "月次"]):
sum_df = pd.concat([uri_df.resample(symbol).sum(),
kai_df.resample(symbol).sum()],
axis=1).fillna(0)
print("注文合計額平均({})".format(name))
print(sum_df.mean())
sum_df.iplot(title="注文金額推移({}合計)".format(name),
kind="spread")
count_df = pd.concat([uri_df.resample(symbol).count(),
kai_df.resample(symbol).count()],
axis=1).fillna(0)
print("注文頻度平均({})".format(name))
print(count_df.mean())
count_df.iplot(title="注文頻度推移({}合計)".format(name),
kind="spread")
display(df)
また、resampleを使った集計を行えば、指定した期間内でデータが存在しない日をゼロとして集計することができる(可視化に便利)
pd.DataFrame(extracted_df['count']).resample('D').sum()
shiftの活用
shift
を使うことで、行や列をずらすことができる。
# 元データ
data_resample
>>>
BRK-A ^GSPC
Date
2009-12-31 99200.000000 1115.099976
2010-01-31 102636.315789 1123.581582
# shiftの結果
data_resample.shift(1)
>>>
BRK-A ^GSPC
Date
2009-12-31 NaN NaN
2010-01-31 99200.000000 1115.099976
# shiftと組み合わせて変化率の取得
np.log(data_resample/data_resample.shift(1))
>>>
BRK-A ^GSPC
Date
2009-12-31 NaN NaN
2010-01-31 0.034054 0.007577
2010-02-28 0.109991 -0.031115
pandasでデータを行・列(縦・横)方向にずらすshift
diff
やpct_change
でも差分を取得できるらしい。
pandasで行・列の差分・変化率を取得するdiff, pct_change
Grouperの活用
datetimeのデータに対してpd.Grouper
を使うことで特定の期間単位での集計が簡単にできる。
# groupbyに適用するケース
df.groupby(pd.Grouper(freq='2W')).count()
# pivot_tableに適用するケース
df.pivot_table(index=pd.Grouper(freq='2W'), columns='label', aggfunc={'id': 'count'})

9. ユースケース
DataFrameをループ
iterrows()
で縦のループ、iteritems()
で横のループができる。
イテレートされるデータの型は'<class 'pandas.core.series.Series'>'
for index, x_data in x.iterrows():
point = 0
if x_data[10910] > 0:
point += 0.5
if x_data[10940] > 0:
point += 0.5
if x_data[10960] > 0:
point += 0.5
if x_data[11000] > 0:
point += 0.5
# x_data['target'] = point
x.loc[index,'target'] = point
print(index, x_data['target'])
縦持ちから横持ちへの変更
pivot_tableを使えば縦もちを横持ちに変換できる
df_7203.pivot_table(values=['value'], index=['base_date'], columns=['Tag_Summary'], aggfunc='sum')
Python: PandasのDataFrameを横持ち・縦持ちに変換する
行を一つずらす
shift()をつかって実現できる。
DataFrameにもSeriesにも適用でき、デフォルトでは1つ下にずれるので、
1つめの要素はNaNになる
import pandas as pd
>>> df = pd.DataFrame({'a': range(1, 6),
'b': [x**2 for x in range(1, 6)],
'c': [x**3 for x in range(1, 6)]})
>>> df
a b c
0 1 1 1
1 2 4 8
2 3 9 27
3 4 16 64
4 5 25 125
>>> df['shift'] = df['a'].shift().fillna(0)
>>> df
a b c shift
0 1 1 1 0.0
1 2 4 8 1.0
2 3 9 27 2.0
3 4 16 64 3.0
4 5 25 125 4.0
pandasでデータを行・列(縦・横)方向にずらすshift
SQLの取得結果からDF作成
import pandas as pd
import pandas.io.sql as psql
connect = mysql.connector.connect(
user=user, password=password, host=rdshost, db=db_name)
sql = 'SELECT * From Edinet_Api_Return'
data = psql.read_sql(sql, connect)
[実装備忘録] Python3のpandasでMySQLにアクセスする方法
データの先頭数文字の条件を指定
- typeという項目の先頭1文字が1のデータのみを抽出
-
.astype(str)
でデータ型を文字列に変換 -
.str[:1]
で文字列の先頭1文字を抽出
-
order = order[order['type'].astype(str).str[:1] == '1']
最後の行を削除
.rptファイルで最後の行に「〜行処理されました」等入っていて削除したいケースを想定。
# 最後以外の行を抽出
df = df[:-1]
# 最後の行を削除
df.drop(df.tail(1).index)
集計(期間 + id等)
pivot_tableでクロス集計するしかない?
groupbyでMultilevel indexを作ることもできる?
f = df_group.pivot_table(index=pd.Grouper(key="約定年月日",freq="6M"),
columns='no', values='約定金額', aggfunc='count').fillna(0)
また、pivot_tableの時にindexとvaluesで同じキーは指定できない?
以下の通りエラーが出る。
def max_day(p):
return max(p)
# KeyErrorになる
df_group.pivot_table(index=pd.Grouper(key="約定年月日",freq="6M"),
columns='no', values='約定年月日', aggfunc=max_day)
>>>
KeyError['約定年月日']
# こっちはうまくいく
df_group['約定年月日_temp'] = df_group['約定年月日']
df_group.pivot_table(index=pd.Grouper(key="約定年月日",freq="6M"),
columns='no', values='約定年月日_temp', aggfunc=max_day)
pandas pivot_tableの引数aggfuncについて
日付の差分を数値に変換
datetime同士の演算で日数の差(間隔)を求めようとすると単位がdays(datetime)になってしまう。単位をintに直したいときはdatetimeのプロパティにアクセスしてdt.days
でintを求められる。
df['days'] = (df['date'] - today).dt.days
Pythonで経過時間や日時(日付・時刻)の差分を測定・算出
MultiindexのJoin
Joinは自動でindex同士の結合を行うので、indexの形式があっていればmultiindexでも結合ができる
f_multi = pd.DataFrame(f_score.stack()).rename(columns={0: 'F'})
m_multi = pd.DataFrame(m_score.stack()).rename(columns={0: 'M'})
r_multi = pd.DataFrame(r_score.stack()).rename(columns={0: 'R'})
temp = m_multi.join(f_multi)
temp = temp.join(r_multi)

Nanを含むデータに処理を加える
temp_df_10['sample'].apply(lambda x: 'NaNです' if(pd.isnull(x)) else x)
Listも含んだ難しいケースについては以下の記事が参考になりそう。
list - Python pandas apply function if a column value is not NULL - Stack Overflow