【Python機械学習】pandasの基本的な使い方1
pandasの使い方メモ。
機械学習でほぼ必須といわれるライブラリのひとつ。機械学習でよく使うらしいメソッドにしぼっています。
目次
- 目次
- 実行環境
- Pandasとは?
- Pandasのインポート
- データ形式 SeriesとDataFrame
- head()でデータの上から5行のみを見る
- tail()でデータの下5行だけ見る
- データの表示が省略される行数・列数
- loc 必要な値だけを取り出す
- iloc 数字指定で行抽出
- 抽出したデータを別のDataFrameとして再利用するには
- DataFrameに個数のバラバラな配列を渡すと欠損値に
- SeriesをDataFrameに変換するには?
- DataFrameをSeriesに変換するには?
実行環境
Windows10
Anaconda
Python3.7
JupyterLab
機械学習を行う際はJupyterLab
やJupyterNotebook
が使われることが多いかと思います。
データを表やグラフにして確認しながら進めていく分析作業が重要で、Jupyterを使うとその点が便利にできるからだと思います。
VSCodeやPyCharm、Atom、ターミナルからIpythonとかでも出来ますが、表示が異なったり設定の手間が掛かるので、素直に最初からJupyterNotebookを使うのが楽そうかなと思います。
なお、この記事はJupyterLabで作成したipynbファイルをmarkdownに変換したものをそのまま投稿しております。
DataFrameを実行した箇所は、はてなブログで自動的にマス目のついた表にhtml変換されて表示されており、Jupyterでの実際の表示とは異なっていることを断っておきます。
Pandasとは?
前回はNumpyの基本的な使い方をやりました。Numpyは行列計算など数値演算を高速で行うライブラリです。
PandasはNumpyを利用して動いており、Excelのような表形式でデータを簡単に扱えるライブラリです。
互いに似たようなことが出来ますが、Pandasは表示を重視しているせいなのかNumpyに比べて計算が遅いそうなので、そのあたりを考慮して使い分けをするのが良いようです。
Pandasのインポート
PandasはPythonの標準ライブラリではないので、先にpipやconda等でインストールしておきます。
PandasはNumpyを利用して動いていると書きましたが、NumpyをimportせずともPandas単体のみのインポートで動きます。
しかしデータを扱う際にNumpy配列を使ったり計算させたりすることが多いので、大抵はnumpyとpandasは同時にインポートして使われています。
# 両方インポートします import numpy as np import pandas as pd
データ形式 SeriesとDataFrame
Pandasのデータは
- 一次元のデータ構造になった
Series
(シリーズ) - 二次元の
DataFrame
(データフレーム)
のクラスに分かれています。
実際にそれぞれのデータクラスを作ってみてみます。
Seriesクラスの生成
一次元のデータを生成。Seriesクラスに1次元のリストを渡します。
series = pd.Series([1,2,3,4,5]) series
0 1
1 2
2 3
3 4
4 5
dtype: int64
縦に2列で出力され、一番下にはデータのタイプがdtype: int64
と表示されています。64ビットのint型。
列の一番左の(0,1,2,3,4)はindexが自動で表示されております。実際のデータは右の列の「1~5」。
0行目に「1」、1行目に「2」・・・と値が入っています。
Series()
の頭は大文字
「series()」のように小文字で書いてしまうとAttributeError: module 'pandas' has no attribute 'series'
とerrorが出る。
type(データ) 型の確認
通常で型を調べるときと同じく、type(データ)とやると型が調べられます。
type(series)
pandas.core.series.Series
↓ print関数を使うと少し表示が変わります。
print(type(series))
<class 'pandas.core.series.Series'>
shapeで形状の確認
numpyと同じです。
series.shape
(5,)
(5,)となっているので「5行」の1次元。
ndimで次元を確認
Numpyと同様、ndimで配列の次元が確認できます。
series.ndim
1
sizeで全要素数を確認
配列に何個の要素が含まれているかが調べられます。
series.size
5
indexを指定
何のデータか分かるようにindexを指定できます。
series = pd.Series([1,2,3,4,5], index=["Aくん","Bくん","Cくん","Dくん","Eくん"]) series
Aくん 1
Bくん 2
Cくん 3
Dくん 4
Eくん 5
dtype: int64
5つのデータに5つのindexを与えたので上手く行きましたが、互いの個数が合わないとerrorがでます。
仮にindexを6個与えてみれば、次のようなエラーが出ます。
ValueError: Length of passed values is 5, index implies 6
データを変数で代入
リストを変数に格納後、Seriesクラスに渡してみます。
# リスト data = ["あ","い","う","え","お"] index=["Aくん","Bくん","Cくん","Dくん","Eくん"] # Seriesクラスにdataとindexを代入 series = pd.Series( data, index ) series
Aくん あ
Bくん い
Cくん う
Dくん え
Eくん お
dtype: object
Seriesクラスに変数でリストを渡しました。リストの中身を文字列にしたのでデータのタイプがdtype: object
に変化しています。
()内は見やすく上のように改行も可能。
カンマの付け忘れに注意 (この場合dataの後ろ)
データをnumpy配列で渡す
リスト同様。
# numpyで配列生成(1以上~6未満。5個できる) numbers_np = np.arange(1,6) # インデックス index=["Aくん","Bくん","Cくん","Dくん","Eくん"] # Seriesクラスにnumbers_npを代入 series = pd.Series( numbers_np, index ) print("<numpy配列>") print(numbers_np) print() print("<series>") print(series)
<numpy配列>
[1 2 3 4 5]
<series>
Aくん 1
Bくん 2
Cくん 3
Dくん 4
Eくん 5
dtype: int32
「データは1次元でなければならない」
一次元のSeriesクラスに多次元配列のデータを渡すと
Exception: Data must be 1-dimensional
のようなエラーが出ます。
上のコードでいくと、
numbers_np = np.arange(1,6)
を、たとえばnumbers_np = np.arange(1,6).reshape(-1,1)
など、
5行1列(5,1)の2次元に書き換えて実行したりするとエラーになる。
DataFrameクラスの生成
DataFrame()を使うと二次元のデータを生成します。行と列で2次元。
df_test = pd.DataFrame([ [10,20,30], [40,50,60], [70,80,90] ]) df_test
0 | 1 | 2 | |
---|---|---|---|
0 | 10 | 20 | 30 |
1 | 40 | 50 | 60 |
2 | 70 | 80 | 90 |
DataFrame()クラスに、リストが3つ入ったリストを渡しました。
内部のリストがそれぞれ1つの行として表示されています。
- 列の一番左の「0,1,2」はindexで行番号
- 行の一番上の「0,1,2」はcolumnsで列番号
を示していて、指定しなければそれぞれ自動で表示されます。
※ Seriesの時は1次元なのでcolumnsの表示がありません。
<注意>
Seriesの「大文字 S」同様、DataFrame
の「D」と「F」は大文字。
どちらか1つでも小文字だと次のようなerror。
AttributeError: module 'pandas' has no attribute 'Dataframe'
⇐ Fを小文字で書いた
shapeで形状確認
numpyと同じく、そして上のSeriesでも使ったshapeで何行何列のデータか確認できる。
df_test.shape
(3, 3)
ndimで次元数を確認
これもnumpy同様、そして上のSeriesでも書いたように次元数が調べられる。
df_test.ndim
2
全要素数の確認
この場合、3行3列なので、3×3=9個になる。
df_test.size
9
2次元より大きな次元の配列をDataFrameに渡すとどうなる?
Excelの表や行列は「縦×横」の形なので2次元なんだろうと分かりますが、3次元以上のデータをDataFrameに渡すとERRORになります。
でも、3次元以上の配列って何でしょう? 3次元目は高さの次元? 4次元以上は? Excelシートの数みたいなもんか?
何だかよくわかりませんが、とりあえずここでは無視して、やり方だけ確認しておきます。
まずは、Numpyで3次元の配列をreshapeで生成します。
# 3行3列の2次元配列をNumpyで2つ生成する (要素数 18) array_3d = np.arange(18).reshape(2,3,3) print(array_3d) print("\n配列の次元数 : ", array_3d.ndim)
[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]]
配列の次元数 : 3
3行3列が2つでき、次元数3となっています。
これをDataFrameクラスに渡してみますと
pd.DataFrame(array_3d)
上の実行出力は省略しますが、ValueError: Must pass 2-d input
とERRORが出ます。
array_4d = np.arange(24).reshape(2,3,2,2)など、4次元とかにしても同様にエラーが出ます。
「DataFrameには2次元データを渡さなければなりません」
逆に今度はDataFrameに1次元を渡すと?
DataFrameに3次元以上のデータは渡せませんでしたが、1次元を渡すとどうなってしまうのか。
# リスト(1次元) data_lst = ["a","b","c"] # DataFrame df1 = pd.DataFrame(data_lst) # データの中身表示 print("DataFrameの中身") print(df1) print() # データの形状他表示 print("DataFrameの型 : ",type(df1)) print("DataFrameの形状 : ",df1.shape) print("DataFrameの次元数 : ",df1.ndim)
DataFrameの中身
0
0 a
1 b
2 c
DataFrameの型 : <class 'pandas.core.frame.DataFrame'>
DataFrameの形状 : (3, 1)
DataFrameの次元数 : 2
indexが0~2、columnsが0で、3行1列、2次元のDataFrame型です。
DataFrameに1次元のデータを渡しても、あくまでも2次元のデータになる。
Seriesデータを列や行に追加したりする時に次元数や型に注意が必要です。これはあとで扱います。
indexとcolumnsを指定
無指定だと自動で「0,1,2・・・」とつくけど味気ないので、独自で用意してみる。
# numpyで、0~100で3行3列のint型乱数をNumpy配列で生成 np_data = np.random.randint(0,101,9).reshape(3,3) # インデックス index = ["呂布","張飛","趙雲"] # 項目 columns = ["剣","槍","弓"] # データフレーム作成 df2 = pd.DataFrame( np_data, index, columns ) df2
※ 数値はランダムです。
行と列に名前をつけただけで、なんか雰囲気が出てきますた。
indexとcolumnsの書き位置について
上のデータフレームを作成する時、indexとcolumnsを書く位置を入れ替えて実行するとどうなるか?
# データフレーム作成 (indexとcolumnsの書く位置を入れ替える)
df3 = pd.DataFrame(
np_data,
columns,
index
)
df3
書く位置を変えただけで、行名と項目名が入れ替わってしまいました。
DataFrame()の引数の順番が決まっている為です。
書く順番が変わっても、次のようにちゃんと指定して書けば大丈夫。
# データフレーム作成
df4 = pd.DataFrame(
np_data,
columns = columns,
index = index
)
df4
ちゃんと狙い通りに戻った。
head()でデータの上から5行のみを見る
head()メソッドを使うと、たくさんあるデータの上から5行だけを取り出して表示できます。
どんなデータが入っているのかの確認に使ったりします。
head()はSeries、DataFrameの両方で使用できます。
データが少ないので増やしてからやりますね。
# インデックス名 index = ["呂布","張飛","趙雲","劉備","諸葛亮","関羽","曹操","孫堅","董卓","袁紹","夏候惇","周瑜","陳宮","張遼","何進"] # 項目名 columns = ["剣","槍","弓","馬","統率","知力"] # numpyをつかい、0以上1未満でfloat型乱数生成。rand(行数m,列数n)でm行n列の行列が生成。 np_data = np.random.rand(len(index), len(columns)) # 代入。変数dfに格納 df = pd.DataFrame( np_data, index = index, columns = columns ) # 上5行だけ表示 df.head()
剣 | 槍 | 弓 | 馬 | 統率 | 知力 | |
---|---|---|---|---|---|---|
呂布 | 0.401721 | 0.417002 | 0.995960 | 0.001314 | 0.423581 | 0.343925 |
張飛 | 0.402860 | 0.779042 | 0.138389 | 0.475487 | 0.060286 | 0.201831 |
趙雲 | 0.507108 | 0.592027 | 0.312652 | 0.896567 | 0.607985 | 0.172778 |
劉備 | 0.170911 | 0.547296 | 0.610188 | 0.263836 | 0.506830 | 0.118035 |
諸葛亮 | 0.794512 | 0.523816 | 0.926814 | 0.507671 | 0.265099 | 0.354000 |
tail()でデータの下5行だけ見る
head()をtail()に変えれば下から5行だけ表示。
こちらもSeries、DataFrameの両方で使用できます。
# 下5行だけ表示
df.tail()
剣 | 槍 | 弓 | 馬 | 統率 | 知力 | |
---|---|---|---|---|---|---|
夏候惇 | 0.484538 | 0.925033 | 0.068624 | 0.290837 | 0.396926 | 0.224444 |
周瑜 | 0.476003 | 0.506794 | 0.321823 | 0.888588 | 0.651754 | 0.272417 |
陳宮 | 0.847366 | 0.131298 | 0.178125 | 0.253371 | 0.681193 | 0.938650 |
張遼 | 0.628514 | 0.934995 | 0.785382 | 0.119538 | 0.104330 | 0.044214 |
何進 | 0.521289 | 0.245135 | 0.870648 | 0.113655 | 0.791690 | 0.645424 |
head()とhead、tail()とtailの表示の違い
()をつけずdf.head
、df.tail
でも実行できるが、表示が変わる。
()を付けない場合、表示がズレ、1行おきの色分けもされません。
ちなみに、ターミナルからIpythonでDataFrameを表示したような場合でも、行ごとの色分けがされません。
実行表示省略します。
データの表示が省略される行数・列数
データが多い場合は、表で一部のデータが表示されなくなり省略されます。
Series、DataFrameともに、データの形状が
- 行 : 60行以下 (Seriesはこちら)
- 列 : 20列以下
の場合は、全てのデータを表示。
それを超えると、つまりSeriesは(61,)、DataFrameは(61,21)のshapeの場合は
- 行 : 上下各5行 (Seriesはこちら)
- 列 : 左右各10列
は表示して、中間は「・・・」と省略された。
全ての環境でそうなるのか、設定できるのか、などは調べてません。
とりあえずスマホでやると、何行何列であろうと非常に見難い(笑)・・・。
loc 必要な値だけを取り出す
「SeriesやDataFrameのデータから、特定の値、特定行や特定の列だけ取り出したい」
というような時、locを使うとできます。
locに似たilocという物がありますが、後でやります。
locを使うときはloc[行名, 列名]
のように具体的なindex名、columns名を指定します。
上で作ったSeriesとDataFrameを使いまわして確認します。
Seriesの場合
とりあえず上で作ったSeriesデータの表示。
# 上で作ったSeriesの確認
series
Aくん 1
Bくん 2
Cくん 3
Dくん 4
Eくん 5
dtype: int32
locでSeriesデータの「値のみ」を抽出
「Cくん」のデータだけ取り出してみる。
「3」が返ってくればOK。
# loc[index名]で値を取り出す series.loc["Cくん"]
3
実は、locをつけなくとも取り出せる。
series["Cくん"]
3
locでindex名と値を同時に抽出
カッコの中をリストにすると
series.loc[["Aくん"]]
Aくん 0
dtype: int32
locで複数のindexと値を抽出
AくんとEくんを取り出してみよう。リストで複数指定する。
series.loc[["Aくん","Eくん"]]
Aくん 0
Eくん 4
dtype: int32
locをつけずとも同様。
series[["Aくん","Eくん"]]
Aくん 0
Eくん 4
dtype: int32
locで範囲を指定し抽出
C~Eくんを抽出する。スライスを使う
<注意>
スライスの、指定した後ろの値も含まれる。
series.loc["Cくん":"Eくん"]
Cくん 2
Dくん 3
Eくん 4
dtype: int32
locを外しても同様に↓。
series["Cくん":"Eくん"]
Cくん 2
Dくん 3
Eくん 4
dtype: int32
DataFrameの場合
DataFrameの場合は、loc[ 行範囲 , 列範囲 ]
とすると指定の行と列を取り出せる。
列範囲を省略し行のみを指定すると、指定行を全列抽出する。
DataFrameデータの確認
こちらも上で作ったものを使いまわします。
locでDataFrameの特定行を抽出
indexだけ指定すると(columnsの指定を省略すると)、その行のみを全列抽出する。
諸葛亮の行を取り出してみる。
df.loc["諸葛亮"]
剣 0.794512
槍 0.523816
弓 0.926814
馬 0.507671
統率 0.265099
知力 0.354000
Name: 諸葛亮, dtype: float64
DataFrameの場合、locを外して実行したら、ERRORになりました。
SeriesもDataFrameも、ちゃんとlocをつけた方がいいですね。
locで複数の指定行を抽出
df.loc[["曹操","夏候惇","呂布"]]
剣 | 槍 | 弓 | 馬 | 統率 | 知力 | |
---|---|---|---|---|---|---|
曹操 | 0.980313 | 0.481871 | 0.237070 | 0.216141 | 0.630027 | 0.194746 |
夏候惇 | 0.484538 | 0.925033 | 0.068624 | 0.290837 | 0.396926 | 0.224444 |
呂布 | 0.401721 | 0.417002 | 0.995960 | 0.001314 | 0.423581 | 0.343925 |
これも列の指定を省略しているので、全列抽出された。
locで指定行の指定列を抽出
列を取り出す場合は、loc[行指定, 列指定]
とすると、指定の行の列を抽出できる。
たとえば、
- 全ての行の
- 「槍」「統率」の列だけ
を取り出したいなら、
- 行 : スライスで全行「:」指定
- 列 : リストで複数指定
のようにする。
df.loc[ : , ["槍","統率"]]
槍 | 統率 | |
---|---|---|
呂布 | 0.417002 | 0.423581 |
張飛 | 0.779042 | 0.060286 |
趙雲 | 0.592027 | 0.607985 |
劉備 | 0.547296 | 0.506830 |
諸葛亮 | 0.523816 | 0.265099 |
関羽 | 0.889468 | 0.905001 |
曹操 | 0.481871 | 0.630027 |
孫堅 | 0.869599 | 0.732994 |
董卓 | 0.464023 | 0.099116 |
袁紹 | 0.050154 | 0.853701 |
夏候惇 | 0.925033 | 0.396926 |
周瑜 | 0.506794 | 0.651754 |
陳宮 | 0.131298 | 0.681193 |
張遼 | 0.934995 | 0.104330 |
何進 | 0.245135 | 0.791690 |
- 「スライスで範囲指定」
- 「リストで個別に複数を指定」
で使い分けすれば狙ったものが自在に取り出せる。
iloc 数字指定で行抽出
上で見てきたように、locは具体的な名前で行や列を指定して抽出しましたが、ilocは整数でindexやcolumnsを指定
し抽出します。
iloc Seriesから値を抽出
# データの表示確認
series
Aくん 1
Bくん 2
Cくん 3
Dくん 4
Eくん 5
dtype: int32
Aくんから順に、index番号は0,1,2・・・です。通常のリストやタプルなどと同じ。
# 最終行指定で抽出するなら series.iloc[-1] # 5
5
# リストでindex指定してindex名も表示 series.iloc[[-1]] # index名と値を出力
Eくん 5
dtype: int32
# 複数indexをリストで指定 # 1と3、即ちBとDを抽出 series.iloc[[1,3]] # B:2 , D:4
Bくん 2
Dくん 4
dtype: int32
iloc Seriesからスライスで抽出
[何以上:何未満]
でスライス。
<注意>
指定した後ろの値は含まれない。
# indexの2~4、即ちC~Dくんを抽出 series.iloc[2:4]
Cくん 2
Dくん 3
dtype: int32
iloc DataFrameから抽出
上で作ったDataFrameをまたまた使い回します。変数df
の変な三国志のやつ。
iloc 行指定抽出
パッと見て、誰が何番のindexかが分かりませんね・・・。
ilocはindex名を付けずに自動で割り振ったような場合に使うのがよさげです。
とはいえ、孫堅を取り出します。0,1,2,と数えて行ったところ上から8番目なので、indexは7。
df.iloc[7]
剣 0.177267
槍 0.869599
弓 0.408910
馬 0.967722
統率 0.732994
知力 0.564545
Name: 孫堅, dtype: float64
index番号を取得するindex.get_loc()
ぐぬぬ...このままでは埒があかぬ。
index.get_loc(インデックス名)
を使えばindex番号が取得できるようじゃ。
袁紹は何番かな?
# データ
df
剣 | 槍 | 弓 | 馬 | 統率 | 知力 | |
---|---|---|---|---|---|---|
呂布 | 0.401721 | 0.417002 | 0.995960 | 0.001314 | 0.423581 | 0.343925 |
張飛 | 0.402860 | 0.779042 | 0.138389 | 0.475487 | 0.060286 | 0.201831 |
趙雲 | 0.507108 | 0.592027 | 0.312652 | 0.896567 | 0.607985 | 0.172778 |
劉備 | 0.170911 | 0.547296 | 0.610188 | 0.263836 | 0.506830 | 0.118035 |
諸葛亮 | 0.794512 | 0.523816 | 0.926814 | 0.507671 | 0.265099 | 0.354000 |
関羽 | 0.776844 | 0.889468 | 0.773801 | 0.381681 | 0.905001 | 0.837660 |
曹操 | 0.980313 | 0.481871 | 0.237070 | 0.216141 | 0.630027 | 0.194746 |
孫堅 | 0.177267 | 0.869599 | 0.408910 | 0.967722 | 0.732994 | 0.564545 |
董卓 | 0.229813 | 0.464023 | 0.239242 | 0.232900 | 0.099116 | 0.032595 |
袁紹 | 0.810562 | 0.050154 | 0.418373 | 0.310994 | 0.853701 | 0.788780 |
夏候惇 | 0.484538 | 0.925033 | 0.068624 | 0.290837 | 0.396926 | 0.224444 |
周瑜 | 0.476003 | 0.506794 | 0.321823 | 0.888588 | 0.651754 | 0.272417 |
陳宮 | 0.847366 | 0.131298 | 0.178125 | 0.253371 | 0.681193 | 0.938650 |
張遼 | 0.628514 | 0.934995 | 0.785382 | 0.119538 | 0.104330 | 0.044214 |
何進 | 0.521289 | 0.245135 | 0.870648 | 0.113655 | 0.791690 | 0.645424 |
# index番号を取り出す df.index.get_loc("袁紹")
9
iloc DataFrameから複数の行指定で抽出
関羽と張遼と何進をilocで取り出す。
だが、index番号が分からないし数えるわけにもいかないので、上で使ったindex.get_loc()
を使います。
# index番号を取得 id_1 = df.index.get_loc("関羽") id_2 = df.index.get_loc("張遼") id_3 = df.index.get_loc("何進") # リストで行指定の全列抽出 df.iloc[[id_1, id_2, id_3]]
剣 | 槍 | 弓 | 馬 | 統率 | 知力 | |
---|---|---|---|---|---|---|
関羽 | 0.776844 | 0.889468 | 0.773801 | 0.381681 | 0.905001 | 0.837660 |
張遼 | 0.628514 | 0.934995 | 0.785382 | 0.119538 | 0.104330 | 0.044214 |
何進 | 0.521289 | 0.245135 | 0.870648 | 0.113655 | 0.791690 | 0.645424 |
iloc DataFrameから範囲の行と列を抽出
孫堅~周瑜の行で、列は統率以降全部を取り出してみる。
ですが、ilocはスライスの後ろ側で指定した番号を含まないので、指定の際に+1します。
列番号を調べるにはdf.columns.get_loc("列名")
とすればいいようです。
上で使ったindex.get_loc("行名")
の indexと行名 を columnsと列名 に変えただけ。
# index取得 id_min = df.index.get_loc("孫堅") id_max = df.index.get_loc("周瑜") # columns取得 col_min = df.columns.get_loc("統率") df.iloc[ id_min : id_max+1 , col_min : ]
統率 | 知力 | |
---|---|---|
孫堅 | 0.732994 | 0.564545 |
董卓 | 0.099116 | 0.032595 |
袁紹 | 0.853701 | 0.788780 |
夏候惇 | 0.396926 | 0.224444 |
周瑜 | 0.651754 | 0.272417 |
抽出したデータを別のDataFrameとして再利用するには
これまでlocやilocを使って、元々のデータから一部を抽出して来ました。
この方法は、抽出してるだけで元データは上書きされるような事もなくそのまま残こっていますので安心です。
取り出したデータだけを再利用したい場合は
df_ryuubi = df.loc["劉備"]
のように別の適当な変数に格納してやれば、抽出したDataFrameがその変数に格納されます。(Seriesも同様)
DataFrameに個数のバラバラな配列を渡すと欠損値に
ところで、要素数がまちまちの複数のリストをDataFrameクラスにリストで渡すとどうなるでしょうか。
# リスト(個数がバラバラ) lst_1 = [1,2,3] lst_2 = [10,20,30,40,50] lst_3 = [100,200] df_vari = pd.DataFrame([lst_1, lst_2, lst_3]) df_vari
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
0 | 1 | 2 | 3.0 | NaN | NaN |
1 | 10 | 20 | 30.0 | 40.0 | 50.0 |
2 | 100 | 200 | NaN | NaN | NaN |
ERRORは出ない。
個数最大のリストの行に合わせて不足分はNaNで欠損値として表示。
2列目以降は小数点が付いています。
SeriesをDataFrameに変換するには?
Numpyのreshape(行,列)が使えるかな?と試したが、AttributeError: 'Series' object has no attribute 'reshape'
のERRORが出る。
Pandasにreshapeは使えないようです。
DataFrame()にSeriesをそのまま渡すと2次元に変換されたDataFrameができる。
# Series生成 s1 = pd.Series([1,2,3,4,5,6]) # DataFrameクラスに渡して変換 df_s1 = pd.DataFrame(s1) # 形状と次元の確認 print("元のSeriesデータ s1 : 形状:{} 次元:{}".format(s1.shape, s1.ndim)) print("DataFrameに渡した後 df_s1 : 形状:{} 次元:{}".format(df_s1.shape, df_s1.ndim))
元のSeriesデータ s1 : 形状:(6,) 次元:1
DataFrameに渡した後 df_s1 : 形状:(6, 1) 次元:2
一応SeriesとDataFrameをそれぞれ表示させておきます。
後者で2次元になったので、一番上にcolumnsが0と付き、1行おきに色分けもされます。
# 前(Series型)
s1
0 1
1 2
2 3
3 4
4 5
5 6
dtype: int64
# 後(DataFrame型)
df_s1
0 | |
---|---|
0 | 1 |
1 | 2 |
2 | 3 |
3 | 4 |
4 | 5 |
5 | 6 |
DataFrameをSeriesに変換するには?
こんなことをする状況があるのか知らないが、一応。
DataFrameは2次元でSeriesは1次元なので、SeriesにするにはDataFrameを1次元配列の形に変形しないといけません。
Numpyで多次元を1次元に変形するにはravel()
を使うとできますが、Pandasでravel()は使えないようなので、DataFrameを
一旦Numpy配列に変換してから1次元に変形します。
PandasのDataFrameからNumpyのNdarrayに変換
values
を使うとNumpy配列に変換されます。
また変な三国志のやつを使い回します。
# DataFrameをNdarrayに変換して変数に格納 narray_df = df.values # 表示 narray_df
array([[0.40172103, 0.41700196, 0.99596008, 0.00131395, 0.4235807 ,
0.34392501],
[0.40285983, 0.77904236, 0.13838936, 0.4754866 , 0.06028554,
0.20183112],
[0.50710816, 0.59202655, 0.31265243, 0.89656746, 0.60798491,
0.17277816],
[0.17091077, 0.54729648, 0.6101883 , 0.26383571, 0.50682996,
0.11803534],
[0.79451234, 0.52381641, 0.92681373, 0.50767126, 0.26509927,
0.35400032],
[0.77684376, 0.88946831, 0.77380134, 0.38168061, 0.90500101,
0.83766001],
[0.98031303, 0.4818708 , 0.23706966, 0.21614067, 0.63002656,
0.19474565],
[0.17726671, 0.86959902, 0.40890954, 0.96772171, 0.73299389,
0.56454476],
[0.22981335, 0.46402294, 0.23924217, 0.23290045, 0.09911601,
0.03259544],
[0.81056219, 0.05015428, 0.41837329, 0.31099448, 0.85370138,
0.78877963],
[0.48453787, 0.92503338, 0.06862379, 0.29083687, 0.39692594,
0.22444407],
[0.4760027 , 0.5067937 , 0.32182294, 0.88858763, 0.6517536 ,
0.27241705],
[0.84736616, 0.13129806, 0.17812463, 0.25337085, 0.68119349,
0.93865021],
[0.62851363, 0.93499539, 0.78538165, 0.11953763, 0.10433006,
0.04421394],
[0.52128914, 0.24513533, 0.87064805, 0.11365535, 0.7916898 ,
0.64542413]])
変な三国志のindex名とcolumns名が消えて、数値だけのデータになりました。
一応、形状と次元と型を確認しておきます。
print(narray_df.shape) print(narray_df.ndim) print(type(narray_df))
(15, 6)
2
<class 'numpy.ndarray'>
15行6列で2次元のNumpy配列ndarrayに変換されています。
これを更に1次元に変形して、PandasのSeriesクラスに渡します。
Numpyで配列を1次元に変形するにはravel()
を使うとできます。
# Numpy配列を、1次元のNumpy配列に変換 new_1d_array = narray_df.ravel() # 形状と次元と型 print(new_1d_array.shape) print(new_1d_array.ndim) print(type(new_1d_array))
(90,)
1
<class 'numpy.ndarray'>
90行、1次元、Numpy配列に変換されましたので、これをPandas.Series()に代入すればSeries型のデータに変換完了。
# Seriesに1次元Numpy配列を代入 new_series = pd.Series(new_1d_array) # 形状と次元と型 print(new_series.shape) print(new_series.ndim) print(type(new_series))
(90,)
1
<class 'pandas.core.series.Series'>
これで15行6列のDataFrameからSeriesに変換することができました。
長いので一旦ここで切ります。
つづきはこちら【Python機械学習】pandasの基本的な使い方2