2.2.10.1ファイルの読み取り
pandasには、表形式になっている形式になっているファイルを読み取れるように機能を提供している。その中で主に使うread_csvとread_tableだけを使ってみよう。
対応するサンプルファイルはコンマで区切られているため、read_csvを使用してdataframeに読み込むことができます。Read_tableの場合は、区切り文字をカンマで指定して読み取ることができます。
In [1]:
!cat ex1.csv
Out [2]:
,a,b,c,d
0,1,2,3,4
1,5,6,7,8
2,9,10,11,12
3,13,14,15,16
In [3]:
df = pd.read_csv('ex1.csv', index_col = 0)
In [4]:
df
Out [5]:
a b c d
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
3 13 14 15 16
In [6]:
df_1.drop(['Unnamed: 0'], axis = 1, inplace = True)
In [7]:
df_1
Out [8]:
a b c d
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
3 13 14 15 16
このとき、意図しないUnnamed:0などの列を追加することができます。 理由は一番最初のcatで確認した結果を見ると、一番前にコンマであることがわかります。 このようになっているデータの場合に発生することになる。 (A1セルにcolumnが空白の場合)
Index_col = 0を追加しながら削除が可能.
In [9]:
df = pd.read_csv('ex1.csv', index_col = 0)
In [10]:
df
Out [11]:
a b c d
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
3 13 14 15 16
あるいは、ドロップメソッドを介しても取り外し可能です。
In [12]:
df_1.drop(['Unnamed: 0'], axis = 1, inplace = True)
In [13]:
df_1
Out [14]:
a b c d
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
3 13 14 15 16
2.2.10.2 大容量ファイルの読み取り
Csv ファイル容量が大きい場合
場合によっては、容量の大きいcsvファイルを読み取ったときにメモリが不足したり、さまざまな理由で問題が発生することがあります。
1つのcsvファイルが大容量の場合、一度に1000個のデータをインポートするようにハンドリングを行うことができます。
chunksize = 10 **3
for cnt, chunk in enumerate(pd.read_csv(filename, chunksize = chunksize)):
do_something(chunk)
csv ファイルが多い場合
日付別にcsvファイルになっている場合、大容量のファイルのようにデータを壊してインポートする必要はないが、一つずつインポートしてconcatenateをする必要があるが、それをするための方法だ。
ディレクトリに存在するファイルだけ繰り返し文を実行し、csvファイルの場合に読み込む方法です。
for filename in os.listdir(dir):
if filename.endswith('.csv'):
df = pd.read_csv(dir + '/' + filename)
2.2.11データの精製と準備
データの分析とモデリングは、データを読み込んだ後、精製および所望の値に処理した後に並べ替えるプロセスに多くの時間がかかります。 この作業は、分析や学習よりも時間がかかることがあり、そのような処理によって結果が異なるため、非常に重要なプロセスです。 今回の章では、欠測値処理、重複データ処理、といったデータ型で処理、データマージ、再配列をしてみよう。
欠測値とは?
欠測値(missing value)は、直訳すれば値がないものである。 欠測値は言語ごとに様々に表現されるが、時系列ではNaN(not a number)で数字ではないことを意味する。
2.2.11.1 欠落しているデータによる処理方法
時系列データでは、欠落しているデータが頻繁に発生する可能性があります。 そのため、欠落しているデータを処理することは頻繁に発生することでもあります。 簡単に処理することは可能ですが、パンダが提供する欠測値を処理する方法は完璧ではないため、分析と学習の結果が異なる可能性があるため、状況に応じて欠測値を処理することを知っておく必要があります。
たとえば、欠損値をすべて削除すると、大量のデータ損失が発生する可能性があり、欠損値が正しく置き換えられない場合、データにバイアスが発生する可能性があります。
欠測値について十分な解釈がなされたら、該当特性を削除するのか、新しい特性に変換するのか、既存の特性を維持しながら欠測値を置換するかを判断しなければならず、通常比率とデータ特性によって次の表のように処理することができる。
欠測値比 | 処理方法 |
10% 未満 | 除去または置換 |
10%以上20%未満 | モデルベースの処理 |
20% 以上 | モデルベースの処理 |
– 置換
文字通り適当な方法で置き換えることだ。 (合理的アプローチ)データの特性に合わせて適切な平均、中間値などで埋めることもでき、他の特性と相関関係がある場合、それに合った値を入れてもよい。.
– モデルベースの処理
欠測値を予測する新しいモデルを構築し、それに基づいて欠測値を埋める方法
2.2.11.2 欠落している値を確認する
最初にNan値があるか確認する方法であるisnull()を用いてどのインデックスにNan値があるか確認が可能で、データが大きくなった場合、総個数やどのインデックスにあるかを確認して処理すればよい。
In [15]:
series = pd.Series([2,4,6,np.nan,10,np.nan])
In [16]:
series
Out [17]:
0 2.0
1 4.0
2 6.0
3 NaN
4 10.0
5 NaN
dtype: float64
In [18]:
series.fillna(1)
Out [19]:
0 2.0
1 4.0
2 6.0
3 1.0
4 10.0
5 1.0
dtype: float64
In [20]:
series.isnull()
Out [21]:
0 False
1 False
2 False
3 True
4 False
5 True
dtype: bool
In [22]:
series.isnull().sum()
Out [23]:
2
In [24]:
np.where(series.isnull())
Out [25]:
(array([3, 5]),)
2.2.11.3 欠測値を処理する
欠測値の場合、別途処理をしないと、既存のデータとデータタイプが異なり、分析やモデリングを動作させる際にエラーが発生することがある。 同じタイプに変更したり削除したりしましょう。
欠測値処理関連メソッド
df.fillna(num) | Nan を num ですべて埋めて返します |
df.dropna() | 欠測値のある行/列の削除 |
df.interpolate() | 直線的にインデックスを無視し、周囲の値を使用して同じ間隔で処理した後に戻ります |
pd.Isnull(df), df.notnull() | 全体の欠損値を確認する |
2.2.11.4 重複排除
– 冗長データの確認
Duplicatedを使用すると、各行が重複しているかseriesに返された値を確認できます。
最初のrowと最後のrowが重複しているかtrueでわかります。
In [26]:
df = pd.DataFrame(np.arange(12).reshape(6,2), index=[1,2,2,3,3,4], columns=['a','b'])
In [27]:
df
Out [28]:
a b
1 0 1
2 2 3
2 4 5
3 6 7
3 8 9
4 10 11
In [29]:
df.iat[5,0] = 0
df.iat[5,1] = 1
In [30]:
df
Out [31]:
a b
1 0 1
2 2 3
2 4 5
3 6 7
3 8 9
4 0 1
In [32]:
df.duplicated()
Out [33]:
1 False
2 False
2 False
3 False
3 False
4 True
dtype: bool
さらに、keep = ‘last’と指定すると、後で重複するデータではなく、前に位置にtrueを与えることもできます。
In [34]:
df.duplicated(keep = 'last')
Out [35]:
1 True
2 False
2 False
3 False
3 False
4 False
dtype: bool
– 重複データの削除
Drop_duplicates() で重複するデータを削除可能。 duplicatedではなくduplicatesであることに注意しましょう。
In [36]:
df.drop_duplicates()
Out [37]:
a b
1 0 1
2 2 3
2 4 5
3 6 7
3 8 9
同様に keep =’last’ を与えると後ろにデータを残し、前にデータを削除することができる。 カラム名を書き留めれば重複確認と削除が可能である。 複数の列を選択したい場合は、リストに追加して可能です。
In [38]:
df
Out [39]:
a b
1 0 1
2 2 3
2 4 5
3 6 7
3 8 9
4 10 1
In [40]:
df.duplicated('b')
Out [41]:
1 False
2 False
2 False
3 False
3 False
4 True
dtype: bool
In [42]:
df.drop_duplicates('b')
Out [43]:
a b
1 0 1
2 2 3
2 4 5
3 6 7
3 8 9
2.2.11.5関数またはマッピングを使用してデータを変換する
dataframeを扱うと、値に別のタイプや新しい値を追加する必要がある場合があります。
例として1つのデータフレームで1行の平均を出したいが、英語スコアがstring型になっていて計算にならないときに型を変更しなければならず、特にdatetimeの場合頻繁に変更しなければならない場合がある。
In [44]:
df = pd.DataFrame([[70, 80, 50],[30, str(30), 40],[76,43,54],[55,75,95]],
columns = ['国語」、「英語」、「数学'])
In [45]:
df
Out [46]:
国語 英語 数学
0 70 80 50
1 30 30 40
2 76 43 54
3 55 75 95
In [47]:
df['英語'].str.contains('0')
Out [48]:
0 NaN
1 True
2 NaN
3 NaN
Name: 英語, dtype: object
2.2.11.6 文字列を置換するかどうかを判断する
pandasが提供するcontainsメソッドを使用して、series内の値にどの文字列が含まれているかを知ることができます。
英語という column 内に string 値で 30 が入っているが、 str.contains() メソッドを通じて ‘0’ があるかどうか検査が可能である。 英語の場合、case = Trueの場合は大文字と小文字を区別します
In [49]:
df = pd.DataFrame([[70, 80, 50],[30, str(30), 40],[76,43,54],[55,75,95]],
columns = ['国語」、「英語」、「数学'])
In [50]:
df
Out [51]:
国語 英語 数学
0 70 80 50
1 30 30 40
2 76 43 54
3 55 75 95
In [52]:
df['英語'].str.contains('0')
Out [53]:
0 NaN
1 True
2 NaN
3 NaN
Name: 英語, dtype: object
– 値を置き換える
Series または daraframe に保存した値を置換したい場合は、基本文字列を変更するときに使用する replace と同じです。 同様にディクショナリーや変えてあげたい一つの変数だけでも可能だ.
In [54]:
df = pd.DataFrame([[70, 80, 50],[30, np.NAN, 40],[76,43,54],[55,75,95]],
columns = ['国語」、「英語」、「数学'])
In [55]:
df
Out [56]:
国語 英語 数学
0 70 80.0 50
1 30 NaN 40
2 76 43.0 54
3 55 75.0 95
In [57]:
df.replace([np.NaN, 30], 0)
Out [58]:
国語 英語 数学
0 70 80.0 50
1 0 0.0 40
2 76 43.0 54
3 55 75.0 95
2.2.11.7 データの組み合わせ
ほとんどのデータは複数のファイルやデータベースで日付などで記録するために分かれている。
分析やモデリングに使用するには、目的の結果が得られるように組み合わせることを知っておく必要があります。 そして今後データを扱いながら最も基本的でもあり、多く使用することになる部分だから必須だと思う。
– dataframeの貼り付け: pd.concat()
Pd.concat 関数の場合 dataframe を物理的につなげてくれる関数である。 そのため、別に重複除去にはならない。
合わされるとき、 default 値として axis=0 が適用されているので、下に dataframe をつなぎます。 ところで、df1にはcolumn dがなく、NaNで満たされたことがわかります。 ちょうど付けるものなのでインデックスが重なるのにignore_index=Trueを追加してインデックスをリセットすることができる。
In [59]:
df1 = pd.DataFrame({'a':['a0','a1','a2','a3'],
'b':['b0','b1','b2','b3'],
'c':['c0','c1','c2','c3']},
index = [0,1,2,3])
df2 = pd.DataFrame({'a':['a2','a3','a4','a5'],
'b':['b2','b3','b4','b5'],
'c':['c2','c3','c4','c5'],
'd':['d2','d3','d4','d5']},
index = [2,3,4,5])
In [60]:
df1
Out [61]:
a b c
0 a0 b0 c0
1 a1 b1 c1
2 a2 b2 c2
3 a3 b3 c3
In [62]:
df2
Out [63]:
a b c d
2 a2 b2 c2 d2
3 a3 b3 c3 d3
4 a4 b4 c4 d4
5 a5 b5 c5 d5
In [64]:
pd.concat([df1,df2])
Out [65]:
a b c d
0 a0 b0 c0 NaN
1 a1 b1 c1 NaN
2 a2 b2 c2 NaN
3 a3 b3 c3 NaN
2 a2 b2 c2 d2
3 a3 b3 c3 d3
4 a4 b4 c4 d4
5 a5 b5 c5 d5
通常のpd.concatを使って合わせるとインデックスもそのままついてしまい、オプションでignore_index = Tureを与えればreset_indexになったインデックスを使うことができる。
In [66]:
pd.concat([df1,df2], ignore_index=True)
Out [67]:
a b c d
0 a0 b0 c0 NaN
1 a1 b1 c1 NaN
2 a2 b2 c2 NaN
3 a3 b3 c3 NaN
4 a2 b2 c2 d2
5 a3 b3 c3 d3
6 a4 b4 c4 d4
7 a5 b5 c5 d5
Joinを通じて重なるイーターだけを合わせることができる。 つなぎ方は outer(合集合), inner(交集合)がある.
In [68]:
pd.concat([df1,df2], join= 'inner')
Out [69]:
a b c
0 a0 b0 c0
1 a1 b1 c1
2 a2 b2 c2
3 a3 b3 c3
2 a2 b2 c2
3 a3 b3 c3
4 a4 b4 c4
5 a5 b5 c5
-dataframe マージ : pd.merge()
Merge()関数は、共通の列に基づいて2つのデータフレームを合計します。 sqlでjoinと同じ役割です。 通常時間を基準に複数のデータを合わせたいときに使用する。
基準列 name が等しい場合 pd.merge(df_left, df_right, how=’ 結合方式, on= 基準列).
In [70]:
df1 = pd.DataFrame(np.arange(10).reshape(5,2), columns = ['a','b'])
df2 = pd.DataFrame(np.arange(12).reshape(6,2), columns = ['a','c'])
In [71]:
df1
Out [72]:
a b
0 0 1
1 2 3
2 4 5
3 6 7
4 8 9
In [73]:
df2
Out [74]:
c d
0 0 1
1 2 3
2 4 5
3 6 7
4 8 9
5 10 11
In [75]:
pd.merge(df1,df2, left_on ='a', right_on='c', how = 'inner')
Out [76]:
a b c d
0 0 1 0 1
1 2 3 2 3
2 4 5 4 5
3 6 7 6 7
4 8 9 8 9
pd.mergeの場合、欠点は2つのdataframeのみを組み合わせることができるということですが、これをreduceという関数を通じてセキュリティできる.
In [77]:
df1 = pd.DataFrame(np.arange(10).reshape(5,2), columns = ['a','b'])
df2 = pd.DataFrame(np.arange(12).reshape(6,2), columns = ['a','c'])
df3 = pd.DataFrame(np.arange(14).reshape(7,2), columns = ['a','d'])
df_list = [df1,df2,df3]
In [78]:
from functools import reduce
reduce(lambda left, right: pd.merge(left, right, on = ['a'], how = 'outer'), df_list)
Out [79]:
a b c d
0 0 1.0 1.0 1
1 2 3.0 3.0 3
2 4 5.0 5.0 5
3 6 7.0 7.0 7
4 8 9.0 9.0 9
5 10 NaN 11.0 11
6 12 NaN NaN 13
-dataframe 구조화 : pd.pivot()
데이터 열 중에서도 두 개의 열을 각각 행 인덱스, 열 인덱스로 사용하고, 데이터를 조회하여 펼쳐 놓는 것을 말한다. Dataframe.pivot(index = ‘인덱스로 사용될 열’, columns = ‘열로 사용될 열’, values = ‘값으로 입력될 열’)
In [80]:
df = pd.DataFrame({'id': [1, 1, 2, 2, 3, 3],
'col': ['x1', 'x2', 'x1', 'x2', 'x1', 'x2'],
'num': [30, 10, 70, 40, 20, 80],
'str': ['a', 'a', 'b', 'b', 'c', 'c']})
In [81]:
df
Out [82]:
id col num str
0 1 x1 30 a
1 1 x2 10 a
2 2 x1 70 b
3 2 x2 40 b
4 3 x1 20 c
5 3 x2 80 c
In [83]:
df.pivot('id','col','num')
Out [84]:
col x1 x2
id
1 a a
2 b b
3 c c
行と列で pivot を行ったときに value がなくなると NaN と表示される。
pd.pivot_table()
pd.pivotになるとエラーが出てはならず、pd.pivot_tableを使用しなければならない場合がいくつかある。 だからだめな状況をあえて経験しないようにするには、 pivot_table だけ知っていても構わない。 さらに、pivot_tableを使用すると、valuesが文字型データの場合はエラーが発生します。 理由は pivot_table の場合 aggfunc 引数を追加的に受けていますが、デフォルト値として mean として適用されているからです。 しかし aggunc = ‘first’ で明示的に設定することで、 default の mean を使って集計するのではなく、再構造化する基準のテーブルで各セルの最初の値 (‘first’) をそのままインポートすることで対応が可能 する。
In [85]:
pd.pivot_table(df, index = 'id', columns = 'col', values = 'str', aggfunc = 'first')
Out [86]:
col x1 x2
id
1 a a
2 b b
3 c c
글 | AI 1팀 김기중