1.概要
CSVファイルをDataFrameで読み込むときCSVファイルの列名が複数行にまたがっている場合がある。
(ひとつのファイルならばそれだけ直せばすむが、同じ配置でCSVファイルが大量にあるときは面倒。。)
そこで、こういった場合の対応案を考えた。
2.やりたいこと
以下のCSVファイルを読み込んで、列名を整理する。
[sample.csv]
,,,,,c5
,x,x,c3,c4,
index,c1,c2,,,x
A,1,2,3,4,5
B,6,7,8,9,10
C,11,12,13,14,15
D,16,17,18,19,20
| col5 | |||||
|---|---|---|---|---|---|
| x | x | col3 | col4 | ||
| index | col1 | col2 | x | ||
| A | 1 | 2 | 3 | 4 | 5 |
| B | 6 | 7 | 8 | 9 | 10 |
| C | 11 | 12 | 13 | 14 | 15 |
- 上3行:列名を含む行(ラベル領域)
- **col1~col5**は列名が記載されたセル
- xは不要な記載のあるセル。
- 空欄:ブランク
- 下3行:データを含む行(データ領域)
↓↓
やりたいこと:これを以下の形になおしたい。
↓↓
| index | col1 | col2 | col3 | col4 | col5 |
|---|---|---|---|---|---|
| A | 1 | 2 | 3 | 4 | 5 |
| B | 6 | 7 | 8 | 9 | 10 |
| C | 11 | 12 | 13 | 14 | 15 |
| D | 16 | 17 | 18 | 19 | 20 |
3.入力データ整理作業
3.1.作業概要
以下の作業を実施する(詳細はこのあと)。
- データ読み込みラベル領域とデータ領域への分割
- ラベル領域から列名リストを作成
- 列名リストをデータ領域に割り当て
3.2手順詳細
3.2.1.データ読み込みとラベル領域とデータ領域への分割
df = pd.read_csv('sample.csv',header =None)
df_label = df1.iloc[:3] #~2行目※がラベル領域@今回のサンプルsample.csvの場合
df_data = df1.iloc[3:] #3行目~がデータ領域
# ※ ここでは、0行目スタート、0列目スタートで数えることにする。
df、df_label、df_dataは以下の通り。
df
| 0 | 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|---|
| 1 | col5 | |||||
| 2 | x | x | col3 | col4 | ||
| 3 | index | col1 | col2 | x | ||
| 4 | A | 1 | 2 | 3 | 4 | 5 |
| 5 | B | 6 | 7 | 8 | 9 | 10 |
| 6 | C | 11 | 12 | 13 | 14 | 15 |
df_label
| 0 | 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|---|
| 0 | NaN | NaN | NaN | NaN | NaN | c5 |
| 1 | NaN | x | x | c3 | c4 | NaN |
| 2 | index | c1 | c2 | NaN | NaN | x |
df_data
| 0 | 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|---|
| 3 | A | 1 | 2 | 3 | 4 | 5 |
| 4 | B | 6 | 7 | 8 | 9 | 10 |
| 5 | C | 11 | 12 | 13 | 14 | 15 |
| 6 | D | 16 | 17 | 18 | 19 | 20 |
3.2.2.ラベル領域から列名リストを作成
ラベル領域を抜き出したdf_labelから列名を抽出する(この節は少し長め)。
df_label
| 0 | 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|---|
| 0 | NaN | NaN | NaN | NaN | NaN | c5 |
| 1 | NaN | x | x | c3 | c4 | NaN |
| 2 | index | c1 | c2 | NaN | NaN | x |
3.2.2.1.不要情報→''に置き換え
以下で不要なNaN、xを''で置き換える処理を実行する。
df_label = df_label.fillna('') #NaNを''に変更
df_label.loc[1,1:2] =''#1行目1,2列の'x'を''に置き換え(地道な手作業、ここも改善できれば。。)
df_label.loc[2,5] ='' #2行目5列の'x'を''に置き換え
上記コード実行後は以下のようになる。
| 0 | 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|---|
| 0 | c5 | |||||
| 1 | c3 | c4 | ||||
| 2 | index | c1 | c2 |
3.2.2.2.転置
このあと行ごとの処理をラクにするため.Tで転置する。
df_label = df_label.T
処理後は以下の通り。
| 0 | 1 | 2 | |
|---|---|---|---|
| 0 | index | ||
| 1 | c1 | ||
| 2 | c2 | ||
| 3 | c3 | ||
| 4 | c4 | ||
| 5 | c5 |
3.2.2.3.列を追加
lblという名前で列を追加する。値は''。
(転置前の表でいうとlblという行を追加したことに対応。行の追加より列の追加の方が簡単。この後の集約も列ごとの方が簡単)
df_label.insert(0,'lbl','')
| lbl | 0 | 1 | 2 | |
|---|---|---|---|---|
| 0 | index | |||
| 1 | c1 | |||
| 2 | c2 | |||
| 3 | c3 | |||
| 4 | c4 | |||
| 5 | c5 |
3.2.2.4.追加した列に列目を集約
以下の処理でlbl列に列名を集約
for i in range(len(df_label.columns)-1):
df_label['lbl'] = df_label['lbl'] + df_label[i]
| lbl | 0 | 1 | 2 | |
|---|---|---|---|---|
| 0 | index | index | ||
| 1 | c1 | c1 | ||
| 2 | c2 | c2 | ||
| 3 | c3 | c3 | ||
| 4 | c4 | c4 | ||
| 5 | c5 | c5 |
3.2.2.5.列名リスト作成
df_label[''lbl]から列名リストを生成する。
lbl_list = df_label['lbl'].tolist()
['index', 'c1', 'c2', 'c3', 'c4', 'c5']
3.2.3.列名リストをデータ領域に割り当て
以下でdf_dataに列名を追加する。
df_data.columns = lbl_list
| index | col1 | col2 | col3 | col4 | col5 | |
|---|---|---|---|---|---|---|
| 3 | A | 1 | 2 | 3 | 4 | 5 |
| 4 | B | 6 | 7 | 8 | 9 | 10 |
| 5 | C | 11 | 12 | 13 | 14 | 15 |
| 6 | D | 16 | 17 | 18 | 19 | 20 |
indexの列を以下で実際にindexに設定する。
df_data
| index | col1 | col2 | col3 | col4 | col5 |
|---|---|---|---|---|---|
| A | 1 | 2 | 3 | 4 | 5 |
| B | 6 | 7 | 8 | 9 | 10 |
| C | 11 | 12 | 13 | 14 | 15 |
| D | 16 | 17 | 18 | 19 | 20 |
完成!!
以上