As you know introduction to the functions of pandas

この記事は[BrainPad Advent Calendar](https://qiita.com/advent-calendar/2022/brainpad)20日目の記事になります

こんにちは[@nissy0409240](https://twitter.com/nissy0409240)です
[@BrainPadProduct](https://twitter.com/brainpadproduct)の中の人として
[エンジニアMeetUp](https://brainpad.connpass.com/event/264376/)の運営と告知をしています
趣味は音楽鑑賞です！
よろしくお願いします！
![スクリーンショット 2022-12-20 14.30.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100333/b64df1a8-f7ad-b444-34f9-bcd3ad723659.png)
2022年もあと一ヶ月を切りましたが
皆様いかがお過ごしでしょうか

私は今年もETLツールの中の人として様々なデータ加工などを行っています
ツールはPythonで作られており、Pandasをよく使ってます
Pandasは現在もバージョンアップされており、今年もいくつかの機能が追加されました
本エントリーでは2022年に入ってから追加されたPandasの機能を2つ紹介します

## tar.gzファイルもそのまま読み込める

Pandasではcsvファイルの読み込み・書き込みが行えるのは周知の事実ですが

```python
>>> import pandas as pd
>>> df = pd.read_csv("./test.csv")
>>> df.to_csv("./out_test.csv")

$ cat ./out_test.csv
hoge,fuga
1,2
3,4
```

1.5.0にバージョンアップされた際に[tar.gz形式のファイルもそのまま読み込めるようになりました](https://pandas.pydata.org/docs/whatsnew/v1.5.0.html#reading-directly-from-tar-archives)
バージョンアップ前はtar.gzファイルを読もうとすると以下のようなエラーが出ていましたが

```python
>>> import pandas as pd
>>> df = pd.read_csv("./test.tar.gz")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/site-packages/pandas/util/_decorators.py", line 311, in wrapper
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/pandas/io/parsers/readers.py", line 680, in read_csv
    return _read(filepath_or_buffer, kwds)
  File "/usr/local/lib/python3.9/site-packages/pandas/io/parsers/readers.py", line 575, in _read
    parser = TextFileReader(filepath_or_buffer, **kwds)
  File "/usr/local/lib/python3.9/site-packages/pandas/io/parsers/readers.py", line 933, in __init__
    self._engine = self._make_engine(f, self.engine)
  File "/usr/local/lib/python3.9/site-packages/pandas/io/parsers/readers.py", line 1235, in _make_engine
    return mapping[engine](f, **self.options)
  File "/usr/local/lib/python3.9/site-packages/pandas/io/parsers/c_parser_wrapper.py", line 75, in __init__
    self._reader = parsers.TextReader(src, **kwds)
  File "pandas/_libs/parsers.pyx", line 544, in pandas._libs.parsers.TextReader.__cinit__
  File "pandas/_libs/parsers.pyx", line 633, in pandas._libs.parsers.TextReader._get_header
  File "pandas/_libs/parsers.pyx", line 847, in pandas._libs.parsers.TextReader._tokenize_rows
  File "pandas/_libs/parsers.pyx", line 1952, in pandas._libs.parsers.raise_parser_error
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 1132: invalid start byte
```

バージョンアップ後はご覧の通りです

```python
# 先ほど使用したtest.csvを圧縮したtest.tar.gzを使用します
>>> import pandas as pd
>>> df = pd.read_csv("./test.tar.gz")
>>> df.to_csv("./out_test_tar_gz.csv")

$ cat ./out_test_tar_gz.csv
hoge,fuga
1,2
3,4
```

## DataFrameでダミーデータを生成する

1.5.0バージョンアップ時に[from_dummies関数が実装されました](https://pandas.pydata.org/docs/whatsnew/v1.5.0.html#from-dummies)
この関数によりダミーデータ生成時にDataFrameを使用することが可能になり
DataFrameでどの値をどう格納するか記述出来るようになりました

実装例は以下の通りです

```python
>>> import pandas as pd
>>> df = pd.DataFrame({"hoge_1": [1, 0, 1], "hoge_2": [0, 1, 0],
...                    "fuga_1": [1, 0, 0], "fuga_2": [0, 1, 0],
...                    "fuga_3": [0, 0, 1]})
>>> pd.from_dummies(df, sep="_")
  hoge fuga
0    1    1
1    2    2
2    1    3
```
カラム名や値に記号を使うことも可能です

```python
>>> import pandas as pd
>>> df = pd.DataFrame({"太郎_○": [1, 0, 1], "太郎_×": [0, 1, 0],
...                    "花子_○": [1, 0, 0], "花子_×": [0, 1, 0],
...                    "花子_△": [0, 0, 1]})
>>> pd.from_dummies(df, sep="_")
  太郎 花子
0  ○  ○
1  ×  ×
2  ○  △
```
注意点はvalueにboolean型以外の値以外の値が格納されたり欠損がある場合は
ダミーデータ生成に失敗します

boolean型以外の値が格納されている場合
```python
>>> import pandas as pd
>>> df = pd.DataFrame({"hoge_1": [1, 0, 1], "hoge_2": [0, 2, 0],
...                    "fuga_1": [1, 0, 0], "fuga_2": [0, 1, 0],
...                    "fuga_3": [0, 0, 1]})
>>> pd.from_dummies(df, sep="_")
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/pandas/core/reshape/encoding.py", line 450, in from_dummies
    data_to_decode = data.astype("boolean", copy=False)
(中略)
  File "/usr/local/lib/python3.9/site-packages/pandas/core/arrays/boolean.py", line 185, in coerce_to_array
    raise TypeError("Need to pass bool-like values")
TypeError: Need to pass bool-like values

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/site-packages/pandas/core/reshape/encoding.py", line 452, in from_dummies
    raise TypeError("Passed DataFrame contains non-dummy data")
TypeError: Passed DataFrame contains non-dummy data
```
欠損がある場合
```python
>>> df = pd.DataFrame({"太郎_○": [1, 0, 1], "太郎_×": [0, 1, 0],
...                    "花子_○": [1, 0, 0], "花子_×": [0, 1, 0],
...                    })
>>> pd.from_dummies(df, sep="_")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/site-packages/pandas/core/reshape/encoding.py", line 507, in from_dummies
    raise ValueError(
ValueError: Dummy DataFrame contains unassigned value(s); First instance in row: 2
```
## 参考

https://pandas.pydata.org/docs/whatsnew/v1.5.0.html