【解説】データサイエンス100本ノック【第1問〜第10問】

【解説】データサイエンス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回答
1
df_receipt.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	sales_ymd	sales_epoch	store_cd	receipt_no	receipt_sub_no	customer_id	product_cd	quantity	amount
0 20181103 1541203200 S14006 112 1 CS006214000001 P070305012 1 158
1 20181118 1542499200 S13008 1132 2 CS008415000097 P070701017 1 81
2 20170712 1499817600 S14028 1102 1 CS028414000014 P060101005 1 170
3 20190205 1549324800 S14042 1132 1 ZZ000000000000 P050301001 1 25
4 20180821 1534809600 S14025 1102 2 CS025415000050 P060102007 1 90
5 20190605 1559692800 S13003 1112 1 CS003515000195 P050102002 1 138
6 20181205 1543968000 S14024 1102 2 CS024514000042 P080101005 1 30
7 20190922 1569110400 S14040 1102 1 CS040415000178 P070501004 1 128
8 20170504 1493856000 S13020 1112 2 ZZ000000000000 P071302010 1 770
9 20191010 1570665600 S14027 1102 1 CS027514000015 P071101003 1 680

これでOKです。

第2問

P-002: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、10件表示させよ。



列指定は``df[["列名", "列名", ・・・]]``だね。10件のみ表示だから``head``メソッドも使おう!



問2回答
1
df_receipt[["sales_ymd", "customer_id", "product_cd", "amount"]].head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	sales_ymd	customer_id	product_cd	amount
0 20181103 CS006214000001 P070305012 158
1 20181118 CS008415000097 P070701017 81
2 20170712 CS028414000014 P060101005 170
3 20190205 ZZ000000000000 P050301001 25
4 20180821 CS025415000050 P060102007 90
5 20190605 CS003515000195 P050102002 138
6 20181205 CS024514000042 P080101005 30
7 20190922 CS040415000178 P070501004 128
8 20170504 ZZ000000000000 P071302010 770
9 20191010 CS027514000015 P071101003 680

これでOKです。

第3問

P-003: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、10件表示させよ。ただし、sales_ymdはsales_dateに項目名を変更しながら抽出すること。



次は``.rename()``メソッドだ!



問3回答
1
df_receipt[["sales_ymd", "customer_id", "product_cd", "amount"]].head(10).rename(columns={'sales_ymd': 'sales_date'})
出力
1
2
3
4
5
6
7
8
9
10
11
12

sales_date customer_id product_cd amount
0 20181103 CS006214000001 P070305012 158
1 20181118 CS008415000097 P070701017 81
2 20170712 CS028414000014 P060101005 170
3 20190205 ZZ000000000000 P050301001 25
4 20180821 CS025415000050 P060102007 90
5 20190605 CS003515000195 P050102002 138
6 20181205 CS024514000042 P080101005 30
7 20190922 CS040415000178 P070501004 128
8 20170504 ZZ000000000000 P071302010 770
9 20191010 CS027514000015 P071101003 680

これでOKです。
だいぶ要領が分かってきたのではないでしょうか?

第4問

P-004: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。

顧客ID(customer_id)が”CS018205000001”



特定の条件を満たした行の取り出しは、``query``メソッドでしたね!



問4回答
1
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']].query('customer_id == "CS018205000001"')
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
	sales_ymd	customer_id	product_cd	amount
36 20180911 CS018205000001 P071401012 2200
9843 20180414 CS018205000001 P060104007 600
21110 20170614 CS018205000001 P050206001 990
27673 20170614 CS018205000001 P060702015 108
27840 20190216 CS018205000001 P071005024 102
28757 20180414 CS018205000001 P071101002 278
39256 20190226 CS018205000001 P070902035 168
58121 20190924 CS018205000001 P060805001 495
68117 20190226 CS018205000001 P071401020 2200
72254 20180911 CS018205000001 P071401005 1100
88508 20190216 CS018205000001 P040101002 218
91525 20190924 CS018205000001 P091503001 280

第5問

P-005: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。

顧客ID(customer_id)が”CS018205000001”
売上金額(amount)が1,000以上



この問題も``query``メソッド!2つの条件を両方満たすことを示すには``&``を使用します。



問5回答
1
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']].query('customer_id == "CS018205000001" & amount >= 1000')
出力
1
2
3
4
sales_ymd	customer_id	product_cd	amount
36 20180911 CS018205000001 P071401012 2200
68117 20190226 CS018205000001 P071401020 2200
72254 20180911 CS018205000001 P071401005 1100

第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条件をは``|``を使用します。



問6回答
1
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'quantity', 'amount']].query('customer_id == "CS018205000001" & (amount >= 1000 | quantity >= 5)')
出力
1
2
3
4
5
6
	sales_ymd	customer_id	product_cd	quantity	amount
36 20180911 CS018205000001 P071401012 1 2200
9843 20180414 CS018205000001 P060104007 6 600
21110 20170614 CS018205000001 P050206001 5 990
68117 20190226 CS018205000001 P071401020 1 2200
72254 20180911 CS018205000001 P071401005 1 1100



「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以下

問7回答
1
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'quantity', 'amount']].query('customer_id == "CS018205000001" & (amount >= 1000 & amount <= 2000)')
出力
1
2
	sales_ymd	customer_id	product_cd	quantity	amount
72254 20180911 CS018205000001 P071401005 1 1100

第8問

P-008: レシート明細のデータフレーム(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。

顧客ID(customer_id)が”CS018205000001”
商品コード(product_cd)が”P071401019”以外

問8回答
1
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'quantity', 'amount']].query('customer_id == "CS018205000001" & product_cd != "P071401019"')
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
	sales_ymd	customer_id	product_cd	quantity	amount
36 20180911 CS018205000001 P071401012 1 2200
9843 20180414 CS018205000001 P060104007 6 600
21110 20170614 CS018205000001 P050206001 5 990
27673 20170614 CS018205000001 P060702015 1 108
27840 20190216 CS018205000001 P071005024 1 102
28757 20180414 CS018205000001 P071101002 1 278
39256 20190226 CS018205000001 P070902035 1 168
58121 20190924 CS018205000001 P060805001 1 495
68117 20190226 CS018205000001 P071401020 1 2200
72254 20180911 CS018205000001 P071401005 1 1100
88508 20190216 CS018205000001 P040101002 1 218
91525 20190924 CS018205000001 P091503001 1 280

第9問

P-009: 以下の処理において、出力結果を変えずにORをANDに書き換えよ。

df_store.query('not(prefecture_cd == "13" | floor_area > 900)')

問9回答
1
df_store.query('prefecture_cd != "13" & floor_area <= 900')
出力
1
2
3
4
store_cd	store_name	prefecture_cd	prefecture	address	address_kana	tel_no	longitude	latitude	floor_area
18 S14046 北山田店 14 神奈川県 神奈川県横浜市都筑区北山田一丁目 カナガワケンヨコハマシツヅキクキタヤマタイッチョウメ 045-123-4049 139.5916 35.56189 831.0
20 S14011 日吉本町店 14 神奈川県 神奈川県横浜市港北区日吉本町四丁目 カナガワケンヨコハマシコウホククヒヨシホンチョウヨンチョウメ 045-123-4033 139.6316 35.54655 890.0
38 S12013 習志野店 12 千葉県 千葉県習志野市芝園一丁目 チバケンナラシノシシバゾノイッチョウメ 047-123-4002 140.0220 35.66122 808.0

第10問

P-010: 店舗データフレーム(df_store)から、店舗コード(store_cd)が”S14”で始まるものだけ全項目抽出し、10件だけ表示せよ。



文字列の前方一致は「カラム名.str.startswith('文字列')」。``query``メソッドで文字列メソッドを使う場合、第2引数に「engine='python'」を指定しないとエラーになるので注意!



問10回答
1
df_store.query('store_cd.str.startswith("S14")', engine='python').head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	store_cd	store_name	prefecture_cd	prefecture	address	address_kana	tel_no	longitude	latitude	floor_area
2 S14010 菊名店 14 神奈川県 神奈川県横浜市港北区菊名一丁目 カナガワケンヨコハマシコウホククキクナイッチョウメ 045-123-4032 139.6326 35.50049 1732.0
3 S14033 阿久和店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁目 カナガワケンヨコハマシセヤクアクワニシイッチョウメ 045-123-4043 139.4961 35.45918 1495.0
4 S14036 相模原中央店 14 神奈川県 神奈川県相模原市中央二丁目 カナガワケンサガミハラシチュウオウニチョウメ 042-123-4045 139.3716 35.57327 1679.0
7 S14040 長津田店 14 神奈川県 神奈川県横浜市緑区長津田みなみ台五丁目 カナガワケンヨコハマシミドリクナガツタミナミダイゴチョウメ 045-123-4046 139.4994 35.52398 1548.0
9 S14050 阿久和西店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁目 カナガワケンヨコハマシセヤクアクワニシイッチョウメ 045-123-4053 139.4961 35.45918 1830.0
12 S14028 二ツ橋店 14 神奈川県 神奈川県横浜市瀬谷区二ツ橋町 カナガワケンヨコハマシセヤクフタツバシチョウ 045-123-4042 139.4963 35.46304 1574.0
16 S14012 本牧和田店 14 神奈川県 神奈川県横浜市中区本牧和田 カナガワケンヨコハマシナカクホンモクワダ 045-123-4034 139.6582 35.42156 1341.0
18 S14046 北山田店 14 神奈川県 神奈川県横浜市都筑区北山田一丁目 カナガワケンヨコハマシツヅキクキタヤマタイッチョウメ 045-123-4049 139.5916 35.56189 831.0
19 S14022 逗子店 14 神奈川県 神奈川県逗子市逗子一丁目 カナガワケンズシシズシイッチョウメ 046-123-4036 139.5789 35.29642 1838.0
20 S14011 日吉本町店 14 神奈川県 神奈川県横浜市港北区日吉本町四丁目 カナガワケンヨコハマシコウホククヒヨシホンチョウヨンチョウメ 045-123-4033 139.6316 35.54655 890.0

まとめ: 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

pandas.DataFrameの行を条件で抽出するquery | note.nkmk.me

コメント