pandas:様々な【データ変換】方法


はじめに

ここに書いてあること

  • データフレームに含まれるデータの変換方法
  • インデックス番号リセット…df.reset_index
  • データ型変更…df.vlaues
  • データ一括変換…df.apply、lambda(lambdaはPython)

前提

サンプルコード

行のインデックス番号のリセット

データ作成

import pandas as pd
df = pd.DataFrame({'a':['01','02','03'],'b':['x','y','z'],'c':[10,20,30]})
df.loc[5]=['05','p',50]
print(df)
print(df.shape)
    a  b   c
0  01  x  10
1  02  y  20
2  03  z  30
5  05  p  50
(4, 3)
  • サイズ(4,3)のデータ(データフレーム)を作成
  • インデックス番号0~2
    • 最初のデータフレーム作成で3行作成
  • インデックス番号5
    • データフレームの更新で1行追加
    • 連番だと次は3になるが5で追加した

インデックス番号をリセット

df.reset_index(drop=True,inplace=True)
print(df)
    a  b   c
0  01  x  10
1  02  y  20
2  03  z  30
3  05  p  50
  • df.reset_indexを使う
    • インデックス番号が5から3になった(0~3の連番)
  • drop=True
    • 元のインデックス番号を保持するかどうか
    • Trueは保持しない
    • drop=Falseがデフォルト値
  • inplace=True
    • 元のデータフレームを更新するかどうか
    • Trueは更新する
    • inplace=Falseがデフォルト値

ndarray(NumPy配列)に変換

データ作成

import numpy as np
import pandas as pd
df = pd.DataFrame(np.arange(12).reshape(3,4), columns=['a','b','c','d'])
print(df)
print(df.shape)
   a  b   c   d
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11
(3, 4)
  • サイズ(3,4)のデータ(データフレーム)を作成

一部取り出してndarrayに変換

p = df[0:2][['a','b','c']]
q = df[0:2][['a','b','c']].values
print(p)
print(type(p))
print(q)
print(type(q))
   a  b  c
0  0  1  2
1  4  5  6
<class 'pandas.core.frame.DataFrame'>
[[0 1 2]
 [4 5 6]]
<class 'numpy.ndarray'>
  • p
    • データを絞り込み抽出
    • 絞り込んだだけなのでDataFrameのまま
  • q
    • df.valuesを使う
    • データ型をndarray(NumPy配列)に変換

一括データ変換

データ作成

import pandas as pd
df = pd.DataFrame({'id':['01','02','03','04','05'],'key':[1,3,2,3,1],'key_value':['','','','',''],'value':[3,4,7,6,5],'sq':['','','','','']})
key_list = {1:'first',2:'second',3:'third'}
print(df)
print(df.shape)
print(key_list)
   id  key key_value  value sq
0  01    1                3
1  02    3                4
2  03    2                7
3  04    3                6
4  05    1                5
(5, 5)
{1: 'first', 2: 'second', 3: 'third'}
  • df
    • サイズ(5,5)のデータ(データフレーム)
    • key_value列とsq列がブランクになっている
    • この2列を次項で一括更新する
  • key_list
    • ディクショナリ型
    • key値1,2,3に対してvalue値first,second,thirdを持っている

例1:べき乗を計算

df['sq']=df['value']**2
print(df)
   id  key key_value  value  sq
0  01    1                3   9
1  02    3                4  16
2  03    2                7  49
3  04    3                6  36
4  05    1                5  25
  • value列のデータを元にべき乗(累乗)を計算
  • sq列に結果を格納している
    • 左辺をdf['value’](またはdf.valueでも可)にすると元のデータを直接更新

例2:関数で更新

df['key_value']=df['key'].apply(lambda x:key_list[x])
print(df)
   id  key key_value  value  sq
0  01    1     first      3   9
1  02    3     third      4  16
2  03    2    second      7  49
3  04    3     third      6  36
4  05    1     first      5  25
  • lambda x:key_list[x]
    • Pythonのlambdaを使って関数作成
    • ディクショナリkey_listを使って値を取得
  • df['key’].apply(…)
    • 計算元データはkey列のデータ
    • df.applyによって引数に指定した関数の処理が実行できる
  • 結果をkey_value列に格納している

文字列をリストに変換する

はじめに

  • pandasではデータをCSVデータから読み込むことがよくあります
  • CSVデータに[1,2,3]のようなリストがあっても文字列として読み込まれます
  • リスト型として処理したい場合、文字列→リストに変換する必要が出てきます

データ作成

import pandas as pd
import ast
df = pd.DataFrame({'id':['01','02','03'],'value':["[1,2,3]","[4,5,6]","[7,8,9]"]})
a = type(df['value'][0])
print(df)
print(df.shape)
print(a)
   id    value
0  01  [1,2,3]
1  02  [4,5,6]
2  03  [7,8,9]
(3, 2)
<class 'str'>
  • サイズ(3,2)のデータ(データフレーム)を作成
  • import ast
    • 文字列をリストに変換するのにast.literal_evalを利用する
  • a
    • データフレームの表示では文字列かどうか判断できない
    • df['value’][0]で1セルのデータ取り出し
    • typeで型を確認するとstr(文字列型)となっていることが分かる

全文

df['value'] = [ast.literal_eval(x) for x in df['value']]
b = type(df['value'][0])
print(df)
print(b)
   id      value
0  01  [1, 2, 3]
1  02  [4, 5, 6]
2  03  [7, 8, 9]
<class 'list'>
  • 見た目は同じに見える
  • b
    • データタイプを確認するとlistになっている
    • 変換の仕組みは以降で説明

部分実行(ast.literal_eval(…))

p = ast.literal_eval('1')
q = ast.literal_eval('1.')
r = ast.literal_eval('[1,2]')
print(p)
print(type(p))
print(q)
print(type(q))
print(r)
print(type(r))
1
<class 'int'>
1.0
<class 'float'>
[1, 2]
<class 'list'>
  • ast.literal_eval(…)の動き
    • 文字列を渡すと適切なデータ型に変換する
    • '1’…int型に変換
    • '1.’…float型に変換
    • '[1,2]’…list型に変換

部分実行([x for x in …])

s = [x for x in pd.Series(['a','b'])]
print(s)
print(type(s))
['a', 'b']
<class 'list'>
  • Pythonのリスト内包表記
  • ループの元になる部分が全文ではpandasのDataFrameになっている
  • 動きの解説
    • 簡単に1列(Series)で考える
    • 'a’と’b’の2つの文字列があるので、2回ループする
    • 展開されて[]内に収まるため、['a’, 'b’]となる
  • 全文では
    • ast.literal_eval(x)変換され、適切なデータ型に変換される
    • 作成されたリスト型が元のデータフレームのvalue列に代入される
    • 結果、value列の全データが適切なデータ型に変換される


Posted by futa