import statsmodels.api as sm
economics_dataset = sm.datasets.get_rdataset('economics', 'ggplot2')
economics = economics_dataset.data
economics.head()
print(economics_dataset.data.__doc__)
rice_dataset = sm.datasets.get_rdataset('rice', 'DAAG')
rice = rice_dataset.data
rice.head()
msleep_dataset = sm.datasets.get_rdataset('msleep', 'ggplot2')
msleep = msleep_dataset.data
msleep.head()
soils_dataset = sm.datasets.get_rdataset('Soils', 'carData')
soils = soils_dataset.data
soils.head()
iris_dataset = sm.datasets.get_rdataset('iris', 'datasets')
iris = iris_dataset.data
iris.head()
orange_dataset = sm.datasets.get_rdataset('Orange', 'datasets')
orange = orange_dataset.data
orange.head()
以下で Pandas の機能を紹介するために、あらかじめ関連するいくつかのパッケージを呼び出して、使えるように準備する。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
Pandas でよく使われるオブジェクト型として Series と DataFrame がある。Series は一次元配列(ベクトル)に似たデータ構造である。Series 型のデータには、位置番号と名前の両方が存在する。そのため、Series 型データから個々の要素を取り出す際に、位置番号と名前の両方を使用することができる。
s = pd.Series([1, 3, 5], index=['apple', 'banana', 'cherry'])
s
s[1]
s['cherry']
また、次のように、Boolean 型の要素からなるリスト・配列 を使用して、要素を取り出すこともできる。
k = [True, False, True]
# k = np.array([True, False, True])
s[k]
k = pd.Series([True, False, True], index=['apple', 'banana', 'cherry'])
s[k]
Series 型のデータの中から重複要素を調べるたり、削除したりするのメソッドには、unique
、value_counts
、duplicated
、drop_duplicates
などがある。
s = pd.Series(['apple', 'apple', 'orange', 'apple', 'cherry', 'orange'])
s
s.unique()
s.value_counts()
s.duplicated()
s.duplicated(keep='last')
s.drop_duplicates()
s.drop_duplicates(keep='last')
crosstab
メソッドは、与えられた 2 つの配列・シリーズに対して、その組み合わせの集計を行うメソッドである。集計結果は、データフレームとして返される。
fruits = np.array(['apple', 'apple', 'banana', 'apple', 'banana', 'cherry', 'apple'])
colors = np.array(['red', 'red', 'yellow', 'green', 'green', 'red', 'red'])
pd.crosstab(fruits, colors, rownames=['fruit'], colnames=['color'])
cut
メソッドは、連続値データを受け取り、それを離散値に変化する機能を持つ。
s = pd.Series([10, 12, 31, 13, 8, 30, 22, 27, 32, 37, 29])
pd.cut(s, bins=3)
ダミー変数を作成するのに便利なメソッドである。
s = ['apple', 'apple', 'banana', 'cherry', 'cherry', 'apple']
pd.get_dummies(s)
s = pd.Series([10, 12, 31, 13, 8, 30, 22, 27, 32, 37, 29])
pd.get_dummies(pd.cut(s, bins=3))
DataFrame は二次元配列(行列)に似たデータ構造である。DataFrame は Series と同様に、要素を位置番号と名前の両方で管理している。そのため、DataFrame から要素を取り出す際に、位置番号と名前の両方で取り出すことができる。ただし、要素を取り出すときは、Series 型のオブジェクトとは異なり、位置番号で要素を取り出すときは iloc
メソッドを介して行い、名前で要素を取り出すときは loc
メソッドを介して行う。
rice データセットには、植物番号(PlantNo)、区画番号(Block)、根部乾燥重量(RootDryMass)、地上部乾燥重量(ShootDryMass)系統(variety)、処理(fert)などのデータが記述されている。このデータセットから variety 列だけを取り出して、variety 列にどんな要素が含まれているのかを調べてみる。
rice.head()
rice_subset = rice.loc[:, 'variety']
rice_subset.head()
variety 列に含まれているユニークな値を出力したい場合は、unique
メソッドを使用する。
rice_subset.unique()
次に、fert 列にはどんな要素が、いくつ含まれているのかを value_counts
メソッドで調べてみる。
rice_subset = rice.loc[:, 'fert']
rice_subset.value_counts()
データフレームから複数の要素を抽出するとき、抽出対象となる列の番号あるいは名前をリストとして与えて、取得する。次は、rice データセットから複数の列(variety、fert、RootDryMass、ShootDryMass)を抽出例となっている。
rice_subset = rice.loc[:, ['variety', 'fert', 'RootDryMass', 'ShootDryMass']]
rice_subset.head()
Boolean 型からなるリスト・配列で取得することもできる。
k = [False, False, True, True, False, True, True]
rice.loc[:, k].head()
# ricce.iloc[:, k].head()
行の抽出も、列の抽出と同様な手順で行う。次は、データフレームの最初の 2 行だけを抽出するときの例である。
rice.loc[0:2, :]
ある列の値に閾値を設けて条件設定を行い、その条件を満たした行だけを抽出することもできる。例えば、fert 列の値が F10 である行を抽出したい場合は、次のように行う。
is_F10 = (rice.loc[:, 'fert'] == 'F10')
rice_subset = rice.loc[is_F10, :]
rice_subset
複数条件を組み合わせて使うこともできる。次は、wt 系統の F10 処理のデータのみを抽出する例である。
is_wt = (rice.loc[:, 'variety'] == 'wt')
is_F10 = (rice.loc[:, 'fert'] == 'F10')
rice_subset = rice.loc[(is_wt & is_F10), :]
rice_subset
wt 系統で RootDryMass が 50 よりも大きく、かつ ShootDryMass が 120 よりも大きい個体を調べてみる。
subset_idx = (rice.loc[:, 'variety'] == 'wt') & (rice.loc[:, 'RootDryMass'] > 50) & (rice.loc[:, 'ShootDryMass'] > 120)
rice_subset = rice.loc[subset_idx, :]
rice_subset
Series 型のデータで使用した unique
、value_counts
、duplicated
、drop_duplicates
などのメソッドは、DataFrame 型のデータに対しても適用できる。
rice.drop_duplicates('variety')
rice.drop_duplicates(['variety', 'fert'])
Pandas では groupby
および apply
メソッドを使用することで、データセットをいくつかのサブセットに分けて集計を行うグループ演算ができる。Pandas で定義されているメソッド(mean
、max
などの常用関数)を使用して集計を行いたい場合は groupby
メソッドを使用する。また、自分で定義した関数を使用して集計したい場合は apply
メソッドを使用する。
次の例は、rice データフレームを variety の値に応じてグループ分けを行い、それぞれのグループの各列に対して平均を求める。
rice_ave = rice.groupby('variety').mean()
rice_ave
RootDryMass および ShootDryMass のみに対して集計を行うとき、該当する列を抽出してから集計を行う。ただし、この場合、グループ分けを行うための情報(variety 列)も合わせて抽出する必要がある。
rice_ave = rice.loc[:, ['variety', 'RootDryMass', 'ShootDryMass']].\
groupby('variety').\
mean()
rice_ave
複数の列の値に基づいて、その組み合わせでグループ分けすることもできる。例えば、系統(variety)と処理(fert)の組み合わせでグループ分けを行い、次に各グループに対して、RootDryMass および ShootDryMass の平均値を計算する場合は、次のようにする。
rice_ave = rice.loc[:, ['variety', 'fert', 'RootDryMass', 'ShootDryMass']].\
groupby(['variety', 'fert']).\
mean()
rice_ave
groupby
メソッドの後に集計処理用のメソッドを付けない場合は、グループ分け後の各サブセットがイテレーターとして処理できるようになる。例えば、各グループの、RootDryMass および ShootDryMass 列に対して、最大値と最小値の差を求めたい場合は、イテレーターを次のように使用する。
df = []
for gname, gdata in rice.loc[:, ['variety', 'RootDryMass', 'ShootDryMass']].groupby(['variety']):
# get maximum values of RootDryMass and ShootDryMass
subset_max = gdata.iloc[:, 1:3].max()
subset_min = gdata.iloc[:, 1:3].min()
# calculate the range
subset_range = subset_max - subset_min
# set up group name to results
subset_range.name = gname
# append the range into `df`
df.append(subset_range)
df = pd.DataFrame(df)
df
group_by
メソッドのイテレーター処理は、apply
メソッドを使って書き換えることもできる。この場合、for
文ブロック内部の処理を関数として定義するしておく必要がある。
def calc_range(x):
# note that x should be a Series or a DataFrame of a subset
# calculate MAX for each column
x_max = x.max()
# calculate MIN for each column
x_min = x.min()
# calculate range for each column
x_range = x_max - x_min
return x_range
rice_ave = rice.loc[:, ['variety', 'fert', 'RootDryMass', 'ShootDryMass']].\
groupby(['variety', 'fert']).\
apply(calc_range)
rice_ave
Pandas では 2 つのデータフレームを結合するときに、concat
メソッドをおよび join
メソッドを使われる。concat
メソッドは 2 つのデータフレームを縦に、または横にそのまま結合させる機能を持つ。join
メソッドは 2 つのデータフレームのある基準列に基づい結合したいときに利用する。
データフレームに列名あるいは行名が付いている場合は、concat
メソッドを使用してデータフレームを結合すると、データフレームの列名あるいは行名が結合する際の位置判断に利用される。
df1 = pd.DataFrame(np.random.randn(3, 3))
df1.columns = ['F1', 'F2', 'F3']
df1.index = ['A', 'B', 'X']
df1
df2 = pd.DataFrame(np.random.randn(4, 3))
df2.columns = ['F1', 'F2', 'F4']
df2.index = ['A', 'B', 'C', 'Y']
df2
1 次元方向にデータフレームを結合したい場合は axis=0
と指定する。
df = pd.concat([df1, df2], axis=0, sort=False)
df
2 次元方向にデータフレームを結合したい場合は axis=1
と指定する。
df = pd.concat([df1, df2], axis=1, sort=False)
df
concat
メソッドを使用するとき、列名あるいは行名をリセットすることで、列名と行名の影響をなくすことができる。行名を無視して結合する時は、ignore_index
オプションが要されているが、このオプションが期待通りに動作しない場合がある。
# same to `pd.concat([df1, df2], axis=0, sort=False)`
df = pd.concat([df1, df2], axis=0, sort=False, ignore_index=True)
df
# same to `pd.concat([df1, df2], axis=1, sort=False)`
df = pd.concat([df1, df2], axis=1, sort=False, ignore_index=True)
df
確実に行名の影響を無くしたい場合は、concat
メソッドのオプションに頼らずに、自分でリセットをかける必要がある。まず、上と同様に、リセットかけずに、結合してみる。
df1 = pd.DataFrame(np.random.randn(3, 3))
df1.columns = ['F1', 'F2', 'F3']
df1.index = ['A', 'B', 'X']
df2 = pd.DataFrame(np.random.randn(4, 3))
df2.columns = ['F1', 'F2', 'F4']
df2.index = ['A', 'B', 'C', 'Y']
df = pd.concat([df1, df2], axis=0, sort=False, ignore_index=True)
df
df1.reset_index(drop=True, inplace=True)
df2.reset_index(drop=True, inplace=True)
df = pd.concat([df1, df2], axis=1, sort=False, ignore_index=True)
df
列名の無視して結合するときのオプションは用意されていないので、列名を自分でリセットする必要がある。
df1 = pd.DataFrame(np.random.randn(3, 3))
df1.columns = ['F1', 'F2', 'F3']
df1.index = ['A', 'B', 'X']
df2 = pd.DataFrame(np.random.randn(4, 3))
df2.columns = ['F1', 'F2', 'F4']
df2.index = ['A', 'B', 'C', 'Y']
df1.columns = range(len(df1.columns))
df2.columns = range(len(df2.columns))
df = pd.concat([df1, df2], axis=0, sort=False)
df
df1 = pd.DataFrame(np.random.randn(3, 3))
df1.columns = ['F1', 'F2', 'F3']
df1.index = ['A', 'B', 'X']
df2 = pd.DataFrame(np.random.randn(4, 3))
df2.columns = ['F1', 'F2', 'F4']
df2.index = ['A', 'B', 'C', 'Y']
df1.columns = range(len(df1.columns))
df2.columns = range(len(df2.columns))
df = pd.concat([df1, df2], axis=1, sort=False)
df
行名と列名の両方をリセットすると、2 つのデータフレームがそのまま結合される。
df1 = pd.DataFrame(np.random.randn(3, 3))
df1.columns = ['F1', 'F2', 'F3']
df1.index = ['A', 'B', 'X']
df2 = pd.DataFrame(np.random.randn(4, 3))
df2.columns = ['F1', 'F2', 'F4']
df2.index = ['A', 'B', 'C', 'Y']
df1.reset_index(drop=True, inplace=True)
df2.reset_index(drop=True, inplace=True)
df1.columns = range(len(df1.columns))
df2.columns = range(len(df2.columns))
df = pd.concat([df1, df2], axis=0, sort=False, ignore_index=True)
df
df1.reset_index(drop=True, inplace=True)
df2.reset_index(drop=True, inplace=True)
df1.columns = range(len(df1.columns))
df2.columns = range(len(df2.columns))
df = pd.concat([df1, df2], axis=1, sort=False, ignore_index=True)
df
merge
メソッドの場合は、2 つのデータフレームを結合する時、両方のデータフレームに存在する同じ名前の列の値を判断して、結合される。行名(および列名)の影響がない。
df1 = pd.concat([pd.Series(['P1', 'P2', 'P3']),
pd.DataFrame(np.random.randn(3, 2))], axis = 1)
df1.columns = ['PlantID', 'root', 'shoot']
df1.index = ['A', 'B', 'C']
df1
df2 = pd.concat([pd.Series(['P1', 'P4', 'P2']),
pd.DataFrame(np.random.randn(3, 2))], axis = 1)
df2.columns = ['PlantID', 'petal', 'sepal']
df2.index = ['X', 'Y', 'Z']
df2
2 つのデータフレームを結合する時に、結合方法(how
)には inner
、outer
、left
、および right
の 4 つの方法が定義されている。何も指定しないときは、inner
として処理される。
# df = pd.merge(df1, df2, on = 'PlantID')
df = pd.merge(df1, df2, on = 'PlantID', how='inner')
df
df = pd.merge(df1, df2, on = 'PlantID', how='outer')
df
df = pd.merge(df1, df2, on = 'PlantID', how='left')
df
df = pd.merge(df1, df2, on = 'PlantID', how='right')
df
二つのデータフレーム間で基準となる列の名前が異なる時は on
オプションの代わりに left_on
および right_on
オプションを使用する。
df1 = pd.concat([pd.Series(['P1', 'P2', 'P3']),
pd.DataFrame(np.random.randn(3, 2))], axis = 1)
df1.columns = ['plant_id', 'root', 'shoot']
df1.index = ['A', 'B', 'C']
df2 = pd.concat([pd.Series(['P1', 'P4', 'P2']),
pd.DataFrame(np.random.randn(3, 2))], axis = 1)
df2.columns = ['PlantID', 'petal', 'sepal']
df2.index = ['X', 'Y', 'Z']
df = pd.merge(df1, df2, left_on = 'plant_id', right_on = 'PlantID', how='outer')
df
同じ列名が存在する時、左側のデータフレームの列名が _x
が、右側のデータフレームの列名が _y
がつけられる。
df1 = pd.concat([pd.Series(['P1', 'P2', 'P3']),
pd.DataFrame(np.random.randn(3, 2))], axis = 1)
df1.columns = ['PlantID', 'root', 'shoot']
df2 = pd.concat([pd.Series(['P1', 'P4', 'P2']),
pd.DataFrame(np.random.randn(3, 2))], axis = 1)
df2.columns = ['PlantID', 'flower', 'shoot']
df = pd.merge(df1, df2, on = 'PlantID', how='outer')
df
suffix
オプションを使用して、列名が重複する際に、重複した名前の後ろに付けられるサフィックスを変更することができる。
df = pd.merge(df1, df2, on = 'PlantID', how='outer', suffixes = ['_left', '_right'])
df
大きさの異なるデータフレームも SQL などのデータベースと同様に join 作業を行うことができる。
df1 = pd.concat([pd.Series(['S1', 'S2', 'S3', 'S1', 'S3']),
pd.DataFrame(np.random.randn(5, 2))], axis = 1)
df1.columns = ['strain', 'root', 'shoot']
df1
df2 = pd.concat([pd.Series(['S1', 'S4', 'S2']),
pd.Series([12, 43, 25])], axis = 1)
df2.columns = ['strain', 'lifespan']
df2
df = pd.merge(df1, df2, on = 'strain', how='outer')
df
df = pd.merge(df1, df2, on = 'strain') # how='inner'
df
表データには様々な種類の表データが存在する。例えば、次のような 2 種類のデータ構造がある。1 つ目のタイプのデータ構造は、1 行が 1 セットのデータを表している。このとき、各列にはそれぞれ異なる属性を持ち、隣り合う列同士の単位が異なっている。2 つ目のタイプのデータ構造は、行列型になっていて、各行と各列がデータの属性を持ち、隣り合う列および隣り合う行同士の単位がすべて同じである。
orange.head()
データフレームと行列間の形式変換は pivot
メソッドを使用する。上での例では、orange のオリジナルデータセットの Tree 列を列名、age 列を行名となるような行列を作るときは、columns
および index
オプションそれぞれに列名と行名を指定し、値 value
を circumference
に指定する。
df = orange.pivot(index='age', columns='Tree', values='circumference').head()
df
行列形式のデータをデータフレーム形式に変換するときは melt
メソッド を使用する。
iris.head()
iris.melt(id_vars=['Species']).head()
iris.melt(id_vars=['Species'], var_name='Type').head()
pivot
および melt
メソッドの他に、stack
および unstack
メソッドも用意されている。stack
および unstack
メソッドは、Series あるいは DataFrame が多重行名が付けられた時に、それらの行名を結合させるか、分離させるかを調整するメソッドである。
pivot
メソッドで変換した表データを元の形に戻すとき、unstack
でデータフレームを崩してから、インデックスをリセットする。
orange.head()
df = orange.pivot(index='age', columns='Tree', values='circumference').head()
df
df.unstack('age').reset_index().head()
melt
、pivot
、unstack
、stack
メソッドを組み合わせることで、グループ集計を行った結果を整形することができる。これらのメソッドの組み合わせによる操作には慣れが必要。
iris.melt(id_vars=['Species'], var_name='Type').\
groupby(['Species', 'Type']).\
mean()
iris.melt(id_vars=['Species'], var_name='Type').\
groupby(['Species', 'Type']).\
mean().\
unstack('Type')
iris.melt(id_vars=['Species'], var_name='Type').\
groupby(['Species', 'Type']).\
mean().\
unstack('Species')
iris.melt(id_vars=['Species'], var_name='Type').\
groupby(['Species', 'Type']).\
mean().\
unstack('Species').\
shape
ある値が欠損値かどうかを調べるときに isna
メソッドあるいは notna
メソッドを使用する。欠損値を調べて、その結果を利用して行または列を抽出すれば、欠損値を含まない行または列を抽出できるようになる。
msleep.head()
msleep.isna().head()
msleep.notna().head()
brainWt 列が欠損値になっていない行を抽出するときは、次のようにする。
msleep.loc[msleep.loc[:, 'brainwt'].notna(), :].head()
欠損地を含む行あるいは列をすべて取り除くときに dropna
メソッドを使用する。
msleep.dropna(axis=0).head()
msleep.dropna(axis=1).head()
Python でグラフを描くときは、matplotlib と seaborn パッケージがよく使われる。これらのパッケージを使うと、複雑なグラフが描けたり、細かい調整ができる。しかし、その反面、操作方法がやや難しい。matplotilb と seaborn のほかに、Pandas パッケージでも簡単な視覚化機能が備えられている。細かい調整ができないものの、Series あるいは DataFrame 型のオブジェクトに plot
や hist
などのメソッドをつけるだけで、グラフが描かれるようになる。データ解析時に、ちょっとデータの分布を確認したいといったときに、非常に便利である。
次のセル内のコードは基本的に実行しなくてもグラフを描くことができる。これらのコードを実行することで、グラフがきれいになる。
sns.set()
sns.set_style("whitegrid")
sns.set_palette('Set1')
fig, ax = plt.subplots()
rice.plot.scatter(x='RootDryMass', y='ShootDryMass', ax=ax)
fig.show()
cols = ["#9b59b6", "#3498db", "#95a5a6", "#e74c3c", "#34495e", "#2ecc71"]
fig, ax = plt.subplots()
i = 0
for group_name, group_subset in rice.groupby('variety'):
ax = group_subset.plot.scatter(x='RootDryMass', y='ShootDryMass', ax=ax, color=cols[i])
i += 1
fig.show()
rice_ave = (
rice.loc[:, ['variety', 'RootDryMass', 'ShootDryMass']]
.groupby('variety')
.mean()
)
fig, ax = plt.subplots()
rice_ave.plot.bar(ax=ax)
fig.show()
fig, ax = plt.subplots()
rice_ave.plot.bar(stacked=True, ax=ax)
fig.show()
rice_ave = (
rice.loc[:, ['variety', 'fert', 'RootDryMass', 'ShootDryMass']]
.groupby(['variety', 'fert'])
.mean()
)
fig, ax = plt.subplots()
rice_ave.plot.bar(ax=ax)
fig.show()
fig, ax = plt.subplots()
rice_ave.plot.bar(stacked=True, ax=ax)
fig.show()
fig, ax = plt.subplots()
rice.plot.box(y = ['RootDryMass', 'ShootDryMass'], ax=ax)
fig.show()
fig, ax = plt.subplots()
rice.loc[:, ['RootDryMass', 'ShootDryMass']].boxplot(ax=ax)
fig.show()
fig, ax = plt.subplots()
rice.loc[:, ['variety', 'RootDryMass', 'ShootDryMass']].\
groupby('variety').\
boxplot(ax=ax)
fig.show()
#fig, ax = plt.subplots()
#rice.loc[:, ['variety', 'fert', 'RootDryMass', 'ShootDryMass']].\
# groupby(['variety', 'fert']).\
# boxplot(ax=ax)
#
#fig.show()
線グラフは時系列を描くときに便利なので、ここでは時系列データを使ってグラフを描く。
economics.head()
fig, ax = plt.subplots()
ax = economics.plot(x='date', y='pce', ax=ax)
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
fig.show()
fig, ax = plt.subplots()
ax = economics.plot(x='date', y=['psavert', 'uempmed'], ax=ax)
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
fig.show()
fig, ax = plt.subplots()
ax = economics.plot(x='date', ax=ax)
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
fig.show()
fig, ax = plt.subplots()
ax = economics.plot(x='date', ax=ax)
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
ax.set_yscale('log')
fig.show()
fig, ax = plt.subplots()
rice.plot.hist(y = 'RootDryMass', ax=ax)
fig.show()
fig, ax = plt.subplots()
## rice.plot.hist(y = ['RootDryMass', 'ShootDryMass'], stacked=False)
rice.plot.hist(y = ['RootDryMass', 'ShootDryMass'], alpha = 0.5, ax=ax)
fig.show()
fig, ax = plt.subplots()
rice.plot.hist(y = ['RootDryMass', 'ShootDryMass'], stacked=True, ax=ax)
fig.show()
iris.head()
plt.rcParams['figure.figsize'] = (10.0, 10.0)
fig, ax = plt.subplots()
pd.plotting.scatter_matrix(iris, ax=ax)
fig.show()
DataFrame メソッドを使用すると、データフレームのデータを画面上に表示させる時に、ハイライトさせることができる。ハイライトを行うために、style.apply
と style.applymap
の 2 つのメソッドが用意されている。style.apply
は各列または各行に対してハイライト処理を行うメソッドである。例えば、各列の最大値を赤くするなどがこれにあたる。これに対して、style.applymap
はデータフレーム全体に対するハイライト処理であり、例えばデータフレーム中のマイナス値を赤くするなどがこれにあたる。
np.random.seed(2019)
df = pd.DataFrame(np.random.randn(4, 6))
df.columns = ['F1', 'F2', 'F3', 'F4', 'F5', 'F6']
df.index = ['A', 'B', 'C', 'D']
df
def highlight_max(val):
val_max = val.max()
highlight_tags = []
for v in val:
if v == val_max:
highlight_tags.append('background-color: orange')
else:
highlight_tags.append('')
return highlight_tags
df.style.apply(highlight_max)
def highlight_max(val):
val_max = val.max()
highlight_tags = []
for v in val:
if v == val_max:
highlight_tags.append('background-color: orange')
else:
highlight_tags.append('')
return highlight_tags
df.style.apply(highlight_max, axis=1)
def highlight_negatives(val):
highlight_tags = ''
if val < 0:
highlight_tags = 'color: #ff0000;'
return highlight_tags
df.style.applymap(highlight_negatives)
df.style.apply(highlight_max).applymap(highlight_negatives)
df.style.apply(highlight_max, subset=['F1', 'F2', 'F3']).\
applymap(highlight_negatives, subset=['F4', 'F5', 'F6'])
df.style.applymap(highlight_negatives, subset=pd.IndexSlice[['A', 'C'], ['F1', 'F3', 'F5']])
画面上に表示されるデータの桁数は style.format
メソッドで調整できる。
df.style.format('{:.2f}')
df.style.format('{:.2f}').format({'F1': '{:.5f}'})
df.iloc[0, 5] = np.nan
df.iloc[2, 2] = np.nan
df.style.highlight_null(null_color='darkgray')
#import seaborn as sns
df.style.background_gradient(cmap='Blues').\
highlight_null(null_color='darkgray')
df.style.bar(color=['lightseagreen', 'sandybrown'], align='mid').highlight_null(null_color='darkgray')
フレームワークを調整した後に、to_excel
メソッドを使用して Excel の形式で保存することもできる。
import openpyxl
df.style.background_gradient(cmap='Blues').\
highlight_null(null_color='#cccccc').\
to_excel('output.xlsx')