Python>pandas>DataFrame:CSVファイル読み込み後の列名整理(列名が複数行にまたがっているとき)


# <a id ="1">1.概要</a>
CSVファイルをDataFrameで読み込むときCSVファイルの列名が複数行にまたがっている場合がある。
(ひとつのファイルならばそれだけ直せばすむが、同じ配置でCSVファイルが大量にあるときは面倒。。)

そこで、こういった場合の対応案を考えた。


# <a id="2">2.やりたいこと</a>
以下の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


| | | | | |<font color=blue>col5| 
|--:|--:|--:|--:|--:|--:|
| | x| x| **<font color ='blue'>col3</font>** | **<font color ='blue'>col4</font>** |
|**<font color='blue'>index</font>** | **<font color ='blue'>col1</font>** | **<font color ='blue'>col2</font>** | | |x | 
| A| 1| 2| 3| 4| 5|
| B| 6| 7| 8| 9|10|
| C|11|12|13|14|15|

>* **上3行：列名を含む行(ラベル領域)**
 *  **<font color ='blue'>col1~col5</font>**は列名が記載されたセル
 * xは不要な記載のあるセル。
 * 空欄：ブランク

>* **下3行：データを含む行(データ領域)**

↓↓
**やりたいこと：これを以下の形になおしたい。**
↓↓

|<font color ='blue'>index</font>|<font color ='blue'>col1</font>|<font color ='blue'>col2</font>|<font color ='blue'>col3</font>|<font color ='blue'>col4</font>|<font color ='blue'>col5</font>|
|--:|--:|--:|--:|--:|--:|
|A| 1| 2| 3| 4| 5|
|B| 6| 7| 8| 9|10|
|C|11|12|13|14|15|
|D|16|17|18|19|20|



# <a id="3">3.入力データ整理作業</a>

## <a id="3.1">3.1.作業概要</a>
以下の作業を実施する(詳細はこのあと)。

1. データ読み込みラベル領域とデータ領域への分割
2. ラベル領域から列名リストを作成
3. 列名リストをデータ領域に割り当て


## <a id="3.2">3.2手順詳細</a>

### <a id="3.2.1">3.2.1.データ読み込みとラベル領域とデータ領域への分割</a>

```python
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`

|&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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|

<br>


`df_label`

|&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;|    0|    1|	  2|  3|  4|  5|
|--:|--:|	--:|--:|--:|--:|--:|
|0| &nbsp; NaN|&nbsp;  NaN|&nbsp; NaN|&nbsp; NaN|&nbsp; NaN| c5|
|1|  NaN|    x|	  x| c3| c4|&nbsp;NaN|
|2|index|   c1|  c2|NaN|NaN|  x|

<br>

`df_data`

|&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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|



### <a id="3.2.2">3.2.2.ラベル領域から列名リストを作成</a>

ラベル領域を抜き出した`df_label`から列名を抽出する(この節は少し長め)。

`df_label`

|&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;|    0|    1|	  2|  3|  4|  5|
|--:|--:|	--:|--:|--:|--:|--:|
|0| &nbsp; NaN|&nbsp;  NaN|&nbsp; NaN|&nbsp; NaN|&nbsp; NaN| c5|
|1|  NaN|    x|	  x| c3| c4|&nbsp;NaN|
|2|index|   c1|  c2|NaN|NaN|  x|


#### <a id="3.2.2.1">3.2.2.1.不要情報→''に置き換え</a>
以下で不要な`NaN`、`x`を`''`で置き換える処理を実行する。

```python
df_label = df_label.fillna('') #NaNを''に変更
df_label.loc[1,1:2] =''#1行目1,2列の'x'を''に置き換え(地道な手作業、ここも改善できれば。。)
df_label.loc[2,5] ='' #2行目5列の'x'を''に置き換え
```

上記コード実行後は以下のようになる。

|&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5|
| --:|--:|--:|--:|--:|--:|--:|
|0| ||||| c5|
|1|  |    |	  | c3| c4||
|2|index|   c1|  c2|||  |

#### <a id="3.2.2.2">3.2.2.2.転置</a>
このあと行ごとの処理をラクにするため`.T`で転置する。

```python
df_label = df_label.T
```
処理後は以下の通り。

| |&nbsp;&nbsp; &nbsp; 0|&nbsp;&nbsp; &nbsp; 1|&nbsp;&nbsp; &nbsp; 2|
|--:|--:|--:|--:|
|0|	|	|	index|
|1|	|	|	c1|
|2|	|	|	c2|
|3|	|	c3|	|
|4|	|	c4|	|
|5|	c5|	|	|


#### <a id="3.2.2.3">3.2.2.3.列を追加</a>
`lbl`という名前で列を追加する。値は`''`。
(転置前の表でいうと`lbl`という行を追加したことに対応。行の追加より列の追加の方が簡単。この後の集約も列ごとの方が簡単)

```python
df_label.insert(0,'lbl','')
```
| |&nbsp;&nbsp; &nbsp; lbl|&nbsp;&nbsp; &nbsp; 0|&nbsp;&nbsp; &nbsp; 1|&nbsp;&nbsp; &nbsp; 2|
|--:|--:|--:|--:|--:|
|0||	|	|	index|
|1||	|	|	c1|
|2||	|	|	c2|
|3||	|	c3|	|
|4||	|	c4|	|
|5||	c5|	|	|


#### <a id="3.2.2.4">3.2.2.4.追加した列に列目を集約</a>
以下の処理で`lbl`列に列名を集約

```python
for i in range(len(df_label.columns)-1):
    df_label['lbl'] = df_label['lbl']  + df_label[i]
```
| |&nbsp;&nbsp; &nbsp; lbl|&nbsp;&nbsp; &nbsp; 0|&nbsp;&nbsp; &nbsp; 1|&nbsp;&nbsp; &nbsp; 2|
|--:|--:|--:|--:|--:|
|0|index||	|	index|
|1|c1|	|	|	c1|
|2|c2|	|	|	c2|
|3|c3|	|	c3|	|
|4|c4|	|	c4|	|
|5|c5|	c5|	|	|

#### <a id="3.2.2.5">3.2.2.5.列名リスト作成</a>
`df_label[''lbl]`から列名リストを生成する。

```python
lbl_list = df_label['lbl'].tolist()
```
['index', 'c1', 'c2', 'c3', 'c4', 'c5']


### <a id="3.2.2">3.2.3.列名リストをデータ領域に割り当て</a>

以下で`df_data`に列名を追加する。

```python
df_data.columns = lbl_list
```

|&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;index|&nbsp;&nbsp;&nbsp;&nbsp; col1|&nbsp;&nbsp;&nbsp;&nbsp;col2|&nbsp;&nbsp;&nbsp;&nbsp;col3|&nbsp;&nbsp;&nbsp;&nbsp;col4| &nbsp;&nbsp;&nbsp;&nbsp;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に設定する。
<br>

`df_data`

|&nbsp;&nbsp;index|&nbsp;&nbsp;&nbsp;&nbsp; col1|&nbsp;&nbsp;&nbsp;&nbsp;col2|&nbsp;&nbsp;&nbsp;&nbsp;col3|&nbsp;&nbsp;&nbsp;&nbsp;col4| &nbsp;&nbsp;&nbsp;&nbsp;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|

完成！！

---


以上