【解説】データサイエンス100本ノック【第1問〜第10問】
当ページのリンクには広告が含まれています。
本記事では一般社団法人データサイエンティスト協会がGitHubに公開している「データサイエンス100本ノック」の問題解説をまとめていきます。
No.1〜No.10までの問題解説をまとめていきますが、最初にNo.1〜No.10の範囲において抑えておくべきポイントをまとめます。
抑えておくべきポイントというのは、Pythonの書き方や考え方のことです。
なお、データサイエンス100本ノックの環境構築方法については、以下の記事にまとめております。
抑えておくPythonのポイント
- データ表示する先頭行の指定:
.head()
メソッド。先頭から数えて()
に指定した数の件数だけデータを表示させるメソッド。df.head(10)
とすると先頭10行が表示される。何も数字を指定しないと5行が表示される。
- 列指定:
df[["列名", "列名", ・・・]]
と書くと特定の列(カラム)のみを抽出したデータフレームを取得することができる。
- 列名変更:
.rename()
メソッド。df[["列名", "列名", ・・・]].rename(columns={'変更するカラム名': '変更後のカラム名'})
とすることで、列名を変更できる。
- 特定の条件を満たした行の取り出し:
.query()
メソッド。()
内に条件を記載すると、条件を満たしたレコードを抽出できる。例えば、列名A
という列に含まれる特定の顧客ID(”CS018205000001”)のみを取り出したいときは、df[['列名A', '列名B', ・・・]].query('列名A == "CS018205000001"')
という記載になる。
- 文字列の前方一致:
カラム名.str.startswith('文字列')
とすることで特定の文字列で始まる行のみを抽出できる。
- pythonで読み込み指定:
.query()
メソッド内部で、先述の文字列の前方一致条件指定すると、TypeError: 'Series' objects are mutable, thus they cannot be hashed
というエラーが発生するときがある。.query()
メソッドで文字列メソッドを使う場合、第2引数にengine='python'
を指定しないといけません。
回答と解説【第1問〜第10問】
以降、問題[第1問(P-001)〜第10問(P-010)]と解説をまとめていきます。
第1問
P-001: レシート明細のデータフレーム(df_receipt)から全項目の先頭10件を表示し、どのようなデータを保有しているか目視で確認せよ。
「全項目の先頭10件を表示」だから``head``メソッドを使おう!
1 | df_receipt.head(10) |
1 | sales_ymd sales_epoch store_cd receipt_no receipt_sub_no customer_id product_cd quantity amount |
これでOKです。
第2問
P-002: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、10件表示させよ。
列指定は``df[["列名", "列名", ・・・]]``だね。10件のみ表示だから``head``メソッドも使おう!
1 | df_receipt[["sales_ymd", "customer_id", "product_cd", "amount"]].head(10) |
1 | sales_ymd customer_id product_cd amount |
これでOKです。
第3問
P-003: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、10件表示させよ。ただし、sales_ymdはsales_dateに項目名を変更しながら抽出すること。
次は``.rename()``メソッドだ!
1 | df_receipt[["sales_ymd", "customer_id", "product_cd", "amount"]].head(10).rename(columns={'sales_ymd': 'sales_date'}) |
1 |
|
これでOKです。
だいぶ要領が分かってきたのではないでしょうか?
第4問
P-004: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。
顧客ID(customer_id)が”CS018205000001”
特定の条件を満たした行の取り出しは、``query``メソッドでしたね!
1 | df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']].query('customer_id == "CS018205000001"') |
1 | sales_ymd customer_id product_cd amount |
第5問
P-005: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。
顧客ID(customer_id)が”CS018205000001”
売上金額(amount)が1,000以上
この問題も``query``メソッド!2つの条件を両方満たすことを示すには``&``を使用します。
1 | df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']].query('customer_id == "CS018205000001" & amount >= 1000') |
1 | sales_ymd customer_id product_cd amount |
第6問
P-006: レシート明細データフレーム「df_receipt」から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上数量(quantity)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。
顧客ID(customer_id)が”CS018205000001”
売上金額(amount)が1,000以上または売上数量(quantity)が5以上
この問題も``query``メソッド!or条件をは``|``を使用します。
1 | df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'quantity', 'amount']].query('customer_id == "CS018205000001" & (amount >= 1000 | quantity >= 5)') |
1 | sales_ymd customer_id product_cd quantity amount |
「xまたはy」とか「xかつy」という条件を意味する記述は、「論理演算子」といいます。
論理演算子は、100本ノックの問題を通じて手を動かしながら慣れていけば大丈夫です。
第7問
P-007: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。
顧客ID(customer_id)が”CS018205000001”
売上金額(amount)が1,000以上2,000以下
1 | df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'quantity', 'amount']].query('customer_id == "CS018205000001" & (amount >= 1000 & amount <= 2000)') |
1 | sales_ymd customer_id product_cd quantity amount |
第8問
P-008: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。
顧客ID(customer_id)が”CS018205000001”
商品コード(product_cd)が”P071401019”以外
1 | df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'quantity', 'amount']].query('customer_id == "CS018205000001" & product_cd != "P071401019"') |
1 | sales_ymd customer_id product_cd quantity amount |
第9問
P-009: 以下の処理において、出力結果を変えずにORをANDに書き換えよ。
df_store.query('not(prefecture_cd == "13" | floor_area > 900)')
1 | df_store.query('prefecture_cd != "13" & floor_area <= 900') |
1 | store_cd store_name prefecture_cd prefecture address address_kana tel_no longitude latitude floor_area |
第10問
P-010: 店舗データフレーム(df_store)から、店舗コード(store_cd)が”S14”で始まるものだけ全項目抽出し、10件だけ表示せよ。
文字列の前方一致は「カラム名.str.startswith('文字列')」。``query``メソッドで文字列メソッドを使う場合、第2引数に「engine='python'」を指定しないとエラーになるので注意!
1 | df_store.query('store_cd.str.startswith("S14")', engine='python').head(10) |
1 | store_cd store_name prefecture_cd prefecture address address_kana tel_no longitude latitude floor_area |
まとめ: 100本ノックをスタートすることができました。
まずは10本のノックを受けきりました。お疲れさまでした。
正直な話、プログラミングを学習する際の一番のハードルは「スタート」です。
学習を始めることが出来た時点で周りと差をつけることができたと思っていいと思います。
今回学んだことのポイントを改めて以下にまとめます。
- データ表示する先頭行の指定:
.head()
メソッド。先頭から数えて()
に指定した数の件数だけデータを表示させるメソッド。df.head(10)
とすると先頭10行が表示される。何も数字を指定しないと5行が表示される。
- 列指定:
df[["列名", "列名", ・・・]]
と書くと特定の列(カラム)のみを抽出したデータフレームを取得することができる。
- 列名変更:
.rename()
メソッド。df[["列名", "列名", ・・・]].rename(columns={'変更するカラム名': '変更後のカラム名'})
とすることで、列名を変更できる。
- 特定の条件を満たした行の取り出し:
.query()
メソッド。()
内に条件を記載すると、条件を満たしたレコードを抽出できる。例えば、列名A
という列に含まれる特定の顧客ID(”CS018205000001”)のみを取り出したいときは、df[['列名A', '列名B', ・・・]].query('列名A == "CS018205000001"')
という記載になる。
- 文字列の前方一致:
カラム名.str.startswith('文字列')
とすることで特定の文字列で始まる行のみを抽出できる。
- pythonで読み込み指定:
.query()
メソッド内部で、先述の文字列の前方一致条件指定すると、TypeError: 'Series' objects are mutable, thus they cannot be hashed
というエラーが発生するときがある。.query()
メソッドで文字列メソッドを使う場合、第2引数にengine='python'
を指定しないといけません。
この調子でどんどん学習を進めていきましょう。
参考記事など
pandas Python Series objects are mutable, thus they cannot be hashed in query method - Stack Overflow