最初に
import pandas
f = [None] * 8
f[0] = pandas.DataFrame(((0, 1), (2, 3)))
ここではデータフレームを複数格納するためのリストfを用意します。
テキストファイルを読み込み、DataFrame構造を確認する
f[0] = pandas.read_csv('data_1.tsv', sep = "\t", index_col = 0)
# 1行目にheader、1列目にindexがあるタブ区切りファイル
print(f[0]) # DataFrame全体を表示
print(type(f[0])) # pandas.core.frame.DataFrame
print(f[0].columns) # 1行目に書かれていたheader(列名)を取得
print(f[0].index) # 1列目に書かれていたindex(行名)を取得
print(f[0].info()) # 各列のデータ型を確認
print(len(f[0])) # 行数を取得 (headerは除く)
print(len(f[0].columns)) # 列数を取得 (indexは除く)
print(f[0].shape) # 行数と列数を取得 (headerやindexは除く)
print(f[0].head(4)) # 先頭4行を表示
print(f[0].tail(4)) # 末尾4行を表示
print(type(f[0].values)) # numpy.ndarray
print(f[0].values) # DataFrameは属性valuesにNumPy配列のobject型として保存されている
f[0] = pandas.read_csv('data_2.tsv', sep = "\t", header = None, index_col = None)
# headerやindexがないファイル
f[0] = pandas.read_csv('data_3.tsv', sep = "\t", index_col = 0, \
header = None, names = ('S1', 'S2', 'S3', 'S4'))
# headerを付けて読み込む
f[0] = pandas.read_csv('data_4.csv', skiprows = 5, encoding = 'Shift_JIS')
# 先頭5行を読み飛ばす, Shift_JISのファイル
読み込まれるデータは、適当に判断されてint, float, strといった型として格納される。慎重に処理したい場合は dtype = object で読み込み、後で astype('float') などと変換すればよい。
サイズを指定し値が初期化されていないデータフレームを作成する
import numpy
f[0] = pandas.DataFrame(numpy.empty((7, 5)))
7行5列のデータフレームを作成。
1つのリストからデータフレームを作成する
f[0] = pandas.DataFrame([3, 8, 5, 4]) # 1行4列ではなく、4行1列DataFrame
f[0] = pandas.DataFrame([3, 8, 5, 4], [5, 2, 1, 9]) # 2つめリストは4行のindexに
f[0] = pandas.DataFrame([[3, 8, 5, 4], [5, 2, 1, 9]]) # 2行4列DataFrame
新規にDataFrameを作成し、headerとindexを付ける
f[0] = pandas.DataFrame([[0.000, 0.000, 0.000, 0.000, 0.000],
[1.000, 1.000, 1.000, 1.000, 1.000],
[1.260, 1.414, 2.000, 4.000, 8.000],
[1.442, 1.732, 3.000, 9.000, 27.000]])
f[0].columns = ['A', 'B', 'C', 'D', 'E'] # headerを付ける、あるいは全体の変更
f[0].index = ['I1', 'I2', 'I3', 'I4'] # indexをつける、あるいは全体の変更
# A B C D E
# I1 0.000 0.000 0.0 0.0 0.0
# I2 1.000 1.000 1.0 1.0 1.0
# I3 1.260 1.414 2.0 4.0 8.0
# I4 1.442 1.732 3.0 9.0 27.0
f[0].rename(columns = {'A': 'a', 'B': 'b'}, index = {'I1': 'i1'}, inplace = True)
# headerおよびindexの一部を変更; 自身を変更する場合は inplace = True
f[0] = d0.rename(columns = {'a': 'aa', 'b': 'bb'}, \
index = {'i1': 'ii1', 'I4': 'ii4'}, inplace = False)
# inplace = False の場合は別なDataFrameに
Excelファイルを読み込みDataFrameにする
book = pandas.ExcelFile('data.xlsx') # 既存ファイルを読み込む
print(type(book)) # pandas.io.excel._base.ExcelFile
print(type(book.sheet_names)) # シート名のlist
for ws in book.sheet_names:
f[0] = book.parse(sheet_name = ws, header = None) # f[0]に上書き
print(ws, f[0], sep = '\n') # シート名とDataFrameの内容を表示
OpenPyXlをインストールする必要がある (xlrd, xlwt, xlsxwriter等は不要)
DataFrameをExcelファイルに書き出す
with pandas.ExcelWriter('data.xlsx') as writer:
data.to_excel(writer, sheet_name = 'data sheet 1')
いくつかのオプションを指定をしてExcelファイルを読み込む
foo = excel.parse(excel.sheet_names[0], skiprows = 10, header = 0, parse_cols = 'C:G, J:K', index_col = 0)
# 最初の10行を読み飛ばし、次の行がheaderで、C列からG列とJ列とK列だけを読み込み、最初のC列をindex
DataFrameをpickleとして書き出し、読み込む
import pickle
with open('data.pickle', 'wb') as pickle_file:
pickle.dump(d0, pickle_file) # pickleファイルとして出力
with open('data.pickle', 'rb') as pickle_file: # 既存pickleから読み込み
d1 = pickle.load(pickle_file)
DataFrameをタブ区切りテキストファイルとして書き出す
f[0].to_csv('data.tsv', sep = '\t', index = True, header = True) # 新規ファイルに出力
Excel等で出力されたShift_JISで書かれたカンマ区切りテキストを読み込む
import codecs # UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte # こんなエラーが出た場合
with codecs.open('data.csv', 'r', 'Shift_JIS', 'ignore') as shift_jis_csv:
f[0] = pandas.read_csv(shift_jis_csv, skiprows = 6) # 先頭6行を無視
print(f[0].iloc[0:8, 0:6]) # 8行6列までを確認
列数が一定でないテキストを読み込む
f[0] = pandas.read_csv('data.csv', names = range(8)) # namesでヘッダを付ける
# ParserError: Error tokenizing data. C error: Expected 1 fields in line 7, saw 10 # こんなエラーを回避
特定の列に列名でアクセスする
print(f[0]['Col3']) # Series
print(f[0].Col3) # Series
print(f[0][['Col5', 'Col3', 'Col1']])
特定の連続行にスライスでアクセスする
print(data[0:1]) # 0行目の1行だけのDataFrame
print(data[3:7]) # 3, 4, 5, 6行目のDataFrame
DataFrameの要素にアクセスする
(n_rows, n_columns) = data.shape # 4096 (len(data) と同じ値), 4096 (len(data.columns) と同じ値)
print(data.iloc[13]) # 0から数えて13行目の1行全体にアクセス
type(data.iat[128, 256]) # numpy.float64; 0から数えて128行256列の要素にアクセス
print(sum(data.iloc[:, 256])) # 256列目全体にアクセスし和を計算
import numpy
print(numpy.std(data.iloc[128, :])) # 128行目全体にアクセスし標準偏差を計算
print(data.iloc[10:20, 40:60]) # 0から数えて、10から19行、40から59列までの部分を表示
print(data.iloc[[10, 20, 30, 40, 50], [150, 160, 170]]) # 指定した行や列のみを表示; headerやindexも表示される
print(data.loc[['foo', 'bar'], data.columns[8]]) # columnsを用いてラベルを取得しlocを利用
print(data.loc[data.index[16:32], 40:50]) # indexを用いてラベルを取得しlocを利用
要素の指定 | 単数要素(高速) | 複数要素(高負荷) |
---|---|---|
ラベルで指定 | at[ , ] | loc[ , ] |
番号で指定 | iat[ , ] | iloc[ , ] |
行ラベルや列ラベルから行や列の番号を取得する
print(d.iat[d.index.get_loc('sample_23'), d.columns.get_loc('feature_19')])
列を追加および削除する
d0['feature13'] = None # 列名を付けて1列追加
d0['feature14'] = [i for i in range(5)] # リストを用意してもう1列追加
d1 =d0.drop(columns = ['feature13', 'feature14']) # タプルではなくリストで, inplace = True でなければ非破壊
del(d0['feature13'], d0['feature14']) # 先に追加した2列を削除
行を追加および削除する
d0.columns = ['ColumnA', 'ColumnB', 'ColumnC', 'ColumnD', 'ColumnE']
d0.index = ['Index01', 'Index02', 'Index03', 'Index04', 'Index05']
d1.columns = ['ColumnA', 'ColumnB', 'ColumnC', 'ColumnD', 'ColumnE'] # 列名を揃えてからappend()
d0 = d0.append(d1)
d0.drop(index = ['Index01', 'Index03', 'Index04', 0, 2]) # index名で指定; 非破壊なのでd0はの中身は変化なし
d1 = d0.drop(index = ['Index01', 'Index03', 'Index04', 0, 2]) # 5行削除されたデータフレームd1
d0.drop(d0.index[[0, 1, 3]], inplace = True) # 行番号で削除したい場合はindex[[]]を利用
転置する
datat = data.T # headerとindexは入れ代わる
pandas.concat()でDataFrameを連結する
print(f[0])
# y2 y3 y4 y5
# x2 4 6 8 10
# x3 6 9 12 15
# x4 8 12 16 20
# x5 10 15 20 25
print(f[1])
# y5 y6 y7 y8
# x4 20 24 28 32
# x5 25 30 35 40
# x6 30 36 42 48
# x7 35 42 49 56
print(pandas.concat(f[:2]), axis = 'index') # headerに基づいて縦方向に連結 (indexの重複あり)
# y2 y3 y4 y5 y6 y7 y8
# x2 4.0 6.0 8.0 10 NaN NaN NaN
# x3 6.0 9.0 12.0 15 NaN NaN NaN
# x4 8.0 12.0 16.0 20 NaN NaN NaN
# x5 10.0 15.0 20.0 25 NaN NaN NaN
# x4 NaN NaN NaN 20 24.0 28.0 32.0
# x5 NaN NaN NaN 25 30.0 35.0 40.0
# x6 NaN NaN NaN 30 36.0 42.0 48.0
# x7 NaN NaN NaN 35 42.0 49.0 56.0
print(pandas.concat(f[:2], axis = 'columns')) # indexに基づいて横方向に連結 (headerの重複あり)
# y2 y3 y4 y5 y5 y6 y7 y8
# x2 4.0 6.0 8.0 10.0 NaN NaN NaN NaN
# x3 6.0 9.0 12.0 15.0 NaN NaN NaN NaN
# x4 8.0 12.0 16.0 20.0 20.0 24.0 28.0 32.0
# x5 10.0 15.0 20.0 25.0 25.0 30.0 35.0 40.0
# x6 NaN NaN NaN NaN 30.0 36.0 42.0 48.0
# x7 NaN NaN NaN NaN 35.0 42.0 49.0 56.0
data = pandas.concat(f[2:5], keys = ('dataframe2', 'dataframe3', 'dataframe4'), axis = 'index')
data = pandas.concat(f[5:8], keys = ('dataframe5', 'dataframe6', 'dataframe7'), axis = 'columns')
keysを用いると、元のデータフレームを区別できます。
数値のみからなるDataFrameをNumPy配列に、またNumPy配列をDataFrameに変換する
data0 = pandas.read_csv('foo.tsv', sep = "\t", index_col = 0) # headerとindex以外は浮動小数点数
import numpy
data = numpy.array(data0.iloc[0:32, 0:16]) # DataFrameの一部を取り出し、NumPy配列へ
numpy.set_printoptions(linewidth = 160, threshold = numpy.inf) # 表示幅を160カラムに広げ、省略せずに全て表示
numpy.set_printoptions(precision = 4, suppress = True) # 小数点以下4桁にまるめ、指数表示せずに
numpy.set_printoptions(formatter = {'float': '{: 0.4f}'.format}) # 小数点以下4桁まで表示
print(type(data)) # numpy.ndarray
print(data.shape) # (32, 16)
print(data)
data1 = pandas.DataFrame(data) # pandasのDataFrameに戻す
print(type(data1)) # pandas.core.frame.DataFrame
print()で表示する際に、折り返されないように、省略されないようにする
pandas.set_option('display.width', 512) # 表示幅を広くする
pandas.set_option('display.max_columns', 8) # 8カラムまで表示
pandas.set_option('display.max_rows', 256) # 265行まで表示
重複する行を削除する
nonredundant = data_frame_1.drop_duplicates() # uniqとは異なり離れている重複行も削除
欠損値か否かを判定する
print(f[0].isna()) # 欠損値は True となる
print(f[0].isnull()) # 同上
print(f[0].dropna() # 欠損値のある行を削除
None あるいは numpy.nan などを代入することで欠損値にすることができる。
平均値など列ごとの統計データを取得する
print(d.count()) # Noneなどでない値の数
print(d.mean()) # 各列の平均 (列数に相当する数の平均値が出力される)
print(d.mean(axis = 1) # 各行の平均 (行数に相当する数の平均値が出力される)
print(d.mean(axis = 'columns') # 各行の平均 (行数に相当する数の平均値が出力される)
print(d.var())
print(d.std())
print(d.min())
print(d.max())
print(d.describe()) # 各種データを出力
print(d.corr()) # 相関係数
print(d['temperature'].mean()) # 特定の列の平均値
散布図行列を描く
pandas.plotting.scatter_matrix(data_frame.iloc[:, 1:5], figsize = (16, 16), c = list(data_frame.iloc[:, 0]), alpha = 1.0)
# 1列から4列目までのデータで散布図, figsizeは単なる図の大きさ, cで0列目のデータで色分けを指定, alphaは透明度で1から0まで小さくすると薄くなる
各列の要素に対して関数を適用する
normalized = data_frame.iloc[:, 1:].apply(lambda x: (x - x.mean()) / x.std(), axis = 0)
# 1列目以降の全ての列に対して、その列の平均で引いた後に標準偏差で割る
Seriesを作り複数のSeriesを列として結合する
s1 = pandas.Series(('foo', 'bar', 'baz')) # リストをSeriesに
s1 = s1.append(pandas.Series(('qux',))) # Seriesにして追加
s2 = pandas.Series((1792, 1804, 1806))
s2 = s2.append(pandas.Series((1811,)))
d = pandas.concat((s1, s2), axis = 1) # 列として結合しデータフレームに
print(d)
# 0 1
# 0 foo 1792
# 1 bar 1804
# 2 baz 1806
# 0 qux 1811
列を指定してソートする
d = pandas.DataFrame(numpy.random.randint(20, 90, (8, 5), dtype = int))
d.index = ['r' + str(i) for i in range(8)]
d.columns = ['c' + str(i) for i in range(5)]
d.sort_values(by = 'c3', ascending = True, inplace = True)
print(d)
# c0 c1 c2 c3 c4
# r2 46 29 62 20 70
# r1 70 65 24 24 38
# r0 33 60 55 42 79
# r5 68 71 73 67 86
# r3 41 68 83 68 49
# r6 37 52 30 73 82
# r4 61 75 36 82 54
# r7 28 55 27 85 61
列内の重複数を確認する
print(d['Name'].value_counts()) # Name列内の重複
ウェブサイトの表を取得する
tables = pandas.read_html(url) # URLの文字列を引数で与えるとDataFrameのリストが得られる
グラフを描く
d.plot() # DrataFrameあるいはSeriesのメソッドplot()で数値列のみの折れ線グラフ
d.plot.bar() # 棒グラフ
d.plot.box() # 箱髭図
d.plot.hist() # ヒストグラム
d.iloc[:, 3].plot.pie() # 円グラフ
条件を指定して各要素に値を代入する
f[0][((f[0].values % 3 == 1) & (f[0] > 50)) | (~ (f[0] > 10))] = numpy.nan
論理積、論理和、否定はそれぞれ &, |, ~ で表現する。
valuesは使わなくても動作する。
上の代入文は、データフレームの全ての値を調べて、3で割った余りが1で、かつ50よりも大きいか、あるいは10以下の要素に対して全て numpy.nan を代入して NaN にする。
全ての要素に対し関数を適用する apply()
def add(x: float, y: float) -> float:
return x + y # xに対しyを足してその結果を返す関数
r = pandas.DataFrame(numpy.empty((3, 5), dtype = float),
index = tuple('ABC'), columns = tuple('abcde')))
print(r)
print(r.loc['B',].apply(add, args = (0.1,))) # 特定の行に対して
print(r['d'].apply(add, args = (0.2,))) # 特定の列に対して
print(r.apply(add, args = (0.7,))) # 全ての要素に対して
print(r) # r自体はapply()によって変化しない
シリアライズする
pickleにするメソッドがあり、ファイル拡張子で xz などと指定すると自動的に圧縮、解凍も行われる。
f[0].to_pickle('f0.xz')
f[1] = pandas.read_pickle('f0.xz')