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 |
完成!!
以上