データサイエンス100本ノック（構造化データ加工編） 1-5本目

python始めたけど、何をしていいのか分からないので、とりあえず問題解くことにしました。
選んだ問題集は「データサイエンス100本ノック（構造化データ加工編）とは何か」。
いろんな人がすでに解答を上げてますが、自分の備忘録として記録。

まず１本目。

# KNOCK-001: データフレームの先頭10件を表示 ★
> レシート明細のデータフレーム（df_receipt）から全項目の先頭10件を表示し、どのようなデータを保有しているか目視で確認せよ。
## 解答
```Python:KNOCK-001
#df_receiptはデータフレーム型（pandas.DataFrame）のオブジェクトで、headはそのメソッド。
df_receipt.head(10)
```

## 備忘録
1本目から難しい。
どうやら、このdf_receiptというのがデータフレームでどうやらオブジェクトのひとつみたい。そしてオブジェクトは、その中にメソッドという関数みたいなモノを持てるみたい。このheadというのがメソッドで、それにアクセスするために、このピリオドで繋げた形で呼び出すみたい。

### DataFrame型の定義
DataFrameはpandas.core.frameモジュール内で定義されている。以下のPATHにある。
```bash
pandas/core/frame.py
```
このファイル内の、DataFrameクラスの定義
DataFrameはNDFrame（N-dimensional frame）という基底クラスを継承しており、二次元のデータを格納するための構造が用意されている。
```python
class DataFrame(NDFrame):
    """
    Two-dimensional, size-mutable, potentially heterogeneous tabular data.
    ...
    """
```
### head()メソッドの実装
```python
def head(self, n=5):
    """
    Return the first `n` rows.

    This function returns the first `n` rows for the object based on position.
    It is useful for quickly testing if your object has the right type of data in it.

    Parameters
    ----------
    n : int, default 5
        Number of rows to select.

    Returns
    -------
    DataFrame or Series
        The first `n` rows of the caller object.
    """
    return self.iloc[:n]
```
head()メソッドの説明
・self: head()メソッドは、DataFrameクラスのインスタンスメソッドとして定義されているため、selfはそのDataFrameオブジェクトを指す。
・n: メソッドの引数で、返す行数を指定してる。デフォルトは5。
self.iloc[:n]: インデックス位置で行を選択するためのilocインデクサーを使用。ilocを使って、DataFrameの最初のn行を選択し、それを返してる。

## 本問から学んだこと
オブジェクト内のメソッドにアクセスする方法

オブジェクト.メソッド名(引数)


# KNOCK-002: 特定の列を抽出する ★
> レシート明細のデータフレーム（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、10件表示させよ。
## 解答
```Python:KNOCK-002
# df_receipt データフレームから 'sales_ymd'（売上日）、'customer_id'（顧客ID）、'product_cd'（製品コード）、'amount'（売上金額）列を抽出
# 抽出したデータフレームの最初の 10 行を表示
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']].head(10)
```

## 備忘録
このダブルブラケットの意味がまた難しい。データフレームを表現するためにはシングルブラケットの中に、リストを入れないといけないみたい。どうやらpandasの仕様みたいなので、もう覚えるしかない。

## 本問から学んだこと
・二重ブラケット [[]]: 常に DataFrame 型を返す。複数の列や1つの列を DataFrame として取り出したいときに使う。
・シングルブラケット []: 1つの列を Series 型で取り出す際に使う。

# KNOCK-003: 指定列の列名を変更する ★
> レシート明細のデータフレーム（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、10件表示させよ。ただし、sales_ymdはsales_dateに項目名を変更しながら抽出すること。
## 解答
```Python:KNOCK-003
# df_receiptデータフレームから指定したカラム（'sales_ymd', 'customer_id', 'product_cd', 'amount'）を抽出
# 'sales_ymd' カラムの名前を 'sales_date' に変更し、先頭から10行を表示する
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']].rename(columns={'sales_ymd': 'sales_date'}).head(10)
```

## 備忘録
### メソッドチェーン
・renameもheadもpandasのDataFrame型のメソッド。メソッドを繋げて用いることをメソッドチェーンと言う。

```python
class DataFrame(NDFrame):
    ...
    def rename(
        self,
        mapper=None,
        *,
        index=None,
        columns=None,
        axis=None,
        copy=True,
        inplace=False,
        level=None,
        errors="ignore",
    ) -> DataFrame | None:
        """
        Alter axes labels.
        ... (ドキュメントと引数の説明が続く)
        """
        ...
        # メソッドの実装が続く
```
### rename()
・rename() メソッドのデフォルトの動作は、「元のデータフレームを変更せず、新しいデータフレームを返すこと」。そのため、元のデータフレーム (df_receipt) のカラム名は変更さない。
変更したい場合は、1) inplace=True を使用するか、2) 変更結果を再代入する。

## 本問から学んだこと
### ・メソッドチェーン
メソッドには繋げて使えるものがある。
### ・rename メソッドの役割
mapper / index / columns: mapperとして辞書を渡すと、インデックスやカラムの名前を変更できる。
inplace: Trueに設定すると、変更が元のデータフレームに適用される。False（デフォルト）に設定すると、新しいデータフレームを返す。

# KNOCK-005: 複数条件に合致する行を抽出する① ★
> P-005: レシート明細のデータフレーム（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、以下の条件を満たすデータを抽出せよ。
顧客ID（customer_id）が"CS018205000001"
売上金額（amount）が1,000以上
## 解答
```Python:KNOCK-005: 
df_tmp.query('customer_id == "CS018205000001" and amount >= 1000')

#別解
df_tmp[(df_tmp['customer_id'] == 'CS018205000001') & (df_tmp['amount'] >= 1000)]
```

## 備忘録
KNOCK-004からcustomer_id == "CS018205000001"もdf_tmp['amount'] >= 1000もブールシリーズ。
```
index     df_tmp['customer_id'] == 'CS018205000001      df_tmp['amount'] >= 1000
0         False                                         False
1         False                                         False
2         False                                         False
3         False                                         False
4         False                                         False
...       ...                                           ...
104676    False                                         False
104677    False                                         False
104678    False                                         False
104679    False                                         False
104680    False                                         False
```
このブールシリーズ２つを比較して、両方Trueのときのみ、Trueとし、さらにブールインデックスを作成する。

## 本問から学んだこと
### &演算子の使い方
& 演算子は、2つのブールシリーズの対応する要素を比較し、両方が True の場合に True を、それ以外は False を返す新しいブールシリーズを作る。