横浜国立大学理工学部建築都市環境系学科卒
一級鉄筋技能士
経済産業省は、デジタル知識・能力を身につけるための実践的な学びの場として、ポータルサイト「マナビDX (デラックス)」を2022年3月から開設しています。
マナビDXの中で出題されているデータ分析の練習問題を解いてみましたので参考にしてください。
目次
マナビDXクエストについて
マナビDXクエストは経産省主催のデジタル育成事業です。
デジタル推進人材育成プログラム「マナビDX Quest」 経済産業省
国は中小企業にAIの積極的な利用を求めている
私たち中小企業は深刻な人材不足に陥っています。
chatGPTをはじめ多くのAIサービスが普及していますが、一般的な市販のAIシステムは高額で、中小企業の人材が簡単に運用できるものではありません。
中小企業はAI導入する作業を慎重に見極め、開発コストを10万円程度に抑えながらDXを進める必要があります。
中小企業が求めているものは小難しい数学の知識やプログラミングの基本知識を問うようなものではなく、具体的な開発事例です。
マナビDXでは実際の中小企業の課題に沿って学習を進められるので、私たち中小企業にとってとてもよい学習機会と言えます。
大手企業のデータサイエンティストのように華麗にプログラミングをすることはできませんが、地道に学習を進めていきましょう。
第1問
問題ではcsv資料が配布され、その資料データを前処理するための基本問題が出題されています。
中小企業にとっては馴染みのない問題ばかりです。
csvファイルの読み込み 条件付き
表「問い合わせ履歴.csv」において、『列「ステータス」がアクティブである』という条件に該当するデータのみを抽出した新たな表を作成しましょう。
このとき、新しく生成された表データの行数はAです。
※ ただし、ヘッダ(列名によって構成される行)は行数のカウントに含めないものとします。
※ 回答は、整数で記入してください。
1 2 3 4 5 6 |
#ダウンロードした資料を個人のgoogledriveに保存マウントします。 from google.colab import drive drive.mount('/content/drive') #pandasライブラリのimport import pandas as pd |
1 2 3 4 5 6 |
#queryメソッドの使用 df = pd.read_csv('/content/drive/MyDrive/マナビDX/問い合わせ履歴.csv', encoding='cp932') df2 = df.query('ステータス in ["アクティブ"]') df2 1270 rows × 9 columns |
csvファイルの読み込み、条件に該当するものを抽出
表「問い合わせ履歴.csv」において、『列「対応所要時間」が200より小さい』という条件に該当するデータのみを抽出した新たな表を作成しましょう。
このとき、新しく生成した表データの行数は
です。
※ ただし、ヘッダ(列名によって構成される行)は行数のカウントに含めないものとします。
※ 回答は、整数で記入してください。
1 2 3 4 5 |
#特定のカラムのデータで条件に該当するものを抽出 df3 = df[df['対応所要時間']<=200] df3 808 rows × 9 columns |
csvファイルの読み込み、複数条件付き
表「問い合わせ履歴.csv」において、『列「対応所要時間」が300以上である』且つ『列「ステータス」が新規である』に該当するデータのみを抽出した新たな表を作成しましょう。
このとき、新しく生成された表データの行数は
です。
※ ただし、ヘッダ(列名によって構成される行)は行数のカウントに含めないものとします。
※ 回答は、整数で記入してください。
1 2 3 4 5 |
#複数条件を&を使用して表現 df4 = df[(df['対応所要時間']>=300) & (df['ステータス'] =='新規')] df4 518 rows × 9 columns |
欠損値の消去
表「問い合わせ履歴.csv」において、列「問い合わせカテゴリ」が空欄(欠損値)の行を削除することで、新たな表を作成しましょう。
このとき、新しく生成された表データの行数は
です。
※ ただし、ヘッダ(列名によって構成される行)は行数のカウントに含めないものとします。
※ 回答は、整数で記入してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#欠損値を持っている行の個数を確認 df.isnull().sum() 問い合わせID 0 ステータス 0 アクティブ 0 問い合わせカテゴリ 326 問い合わせ時刻 0 対応時刻 0 対応所要時間 0 対応者ID 0 初回問い合わせ方法 0 dtype: int64 |
1 2 3 4 5 6 |
#dropnaメソッドで欠損値を消去 #3172-326=2846で検算 df5 = df.dropna() df5 2846 rows × 9 columns |
重複行を取り除く
表「問い合わせ履歴.csv」には、全ての列の値が互いにまったく同じ行(重複行)が含まれています。
そこで、これらの重複行を取り除いた表を新たに作成しましょう。
このとき、新しく生成された表データの行数は
です。
※ ただし、ヘッダ(列名によって構成される行)は行数のカウントに含めないものとします。
※ 回答は、整数で記入してください。
1 2 3 4 |
#duplicatedメソッドで重複行を確認 df[df.duplicated()] 1227 rows × 9 columns |
1 2 3 4 5 6 |
#dropメソッドで重複行を消去 #3172-1227=1945で検算 df.drop_duplicates() 1945 rows × 9 columns |
第2問
pandasを使用したデータの連結、転置などの問題が出てきます。
縦方向のデータの連結 転置
表「来店履歴_1月.csv」と表「来店履歴_2月.csv」を縦方向に連結しましょう。
このとき、連結によって生成された表データにおける列「お支払い額」の平均値は
です。
ただし、「来店履歴_2月.csv」は行と列がひっくり返った状態で保存されています。
そのため、「来店履歴_1月.csv」と連結する前に事前に表の転置を行いましょう。
※ 回答は、小数(小数点以下1桁目までの精度)で記入してください。
仮に、小数点以下2桁目以降の桁まで数が続く場合は、小数第2位の数で四捨五入を行った結果を回答として記入してください。
四捨五入の例)
・0.1234 → 0.1
・5.6789 → 5.7
・-5.6789 → -5.7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
df6 = pd.read_csv('/content/drive/MyDrive/マナビDX/来店履歴_1月.csv', encoding='cp932') df7 = pd.read_csv('/content/drive/MyDrive/マナビDX/来店履歴_2月.csv', encoding='cp932') #Tは転置 df8 = df7.T df8 = df8.drop(df8.index[[0]]) df8 #縦結合appendメソッド df6.columns = df8.columns df9 = df6.append(df8) df9 columns = ['顧客ID','メニューID','来店日','お支払い額','クーポン'] df9.columns = columns df9 2213 rows × 5 columns |
内部結合
表「新規顧客.csv」と表「顧客別売上集計.csv」を、列「顧客ID」をキーとして内部結合しましょう。
このとき、結合によって生成された表データにおける列「年間お支払い額」の平均値は
です。
※ 回答は、小数(小数点以下1桁目までの精度)で記入してください。
仮に、小数点以下2桁目以降の桁まで数が続く場合は、小数第2位の数で四捨五入を行った結果を回答として記入してください。
四捨五入の例)
・0.1234 → 0.1
・5.6789 → 5.7
・-5.6789 → -5.7
1 2 3 4 5 6 7 8 9 |
df10 = pd.read_csv('/content/drive/MyDrive/マナビDX/新規顧客.csv', encoding='cp932') df11 = pd.read_csv('/content/drive/MyDrive/マナビDX/顧客別売上集計.csv', encoding='cp932') #内部結合mergeメソッド #.describe()で平均などの統計量を一発表示 df12 = df10.merge(df11) df12.describe() 6301.912664 |
左外部結合 欠損値を0で補間
表「新規顧客.csv」(左)と表「顧客別売上集計.csv」(右)を、列「顧客ID」をキーとして左外部結合しましょう。
その後、結合後の表データにおいて「年間お支払い額」の列が空欄(欠損値)となった箇所を、0で補間してください。
最後に列「年間お支払い額」の平均値を計算すると、答えは
になります。
※ 回答は、小数(小数点以下1桁目までの精度)で記入してください。
仮に、小数点以下2桁目以降の桁まで数が続く場合は、小数第2位の数で四捨五入を行った結果を回答として記入してください。
四捨五入の例)
・0.1234 → 0.1
・5.6789 → 5.7
・-5.6789 → -5.7
1 2 3 4 5 6 7 8 9 10 11 |
# 左外部結合 df13 = df10.merge(df12, how="left") df13 #空欄(欠損値)となった箇所を0で補間 df14 = df13.fillna(0) df14 df14.describe() 2963.322382 |
並び替え
表「顧客別売上集計.csv」を、年間来店回数が多い順番に行を並び替えましょう。
このとき、並び替えた後の表データの先頭10行における列「年間来店回数」の平均値は
です。
※ 回答は、小数(小数点以下1桁目までの精度)で記入してください。
仮に、小数点以下2桁目以降の桁まで数が続く場合は、小数第2位の数で四捨五入を行った結果を回答として記入してください。
四捨五入の例)
・0.1234 → 0.1
・5.6789 → 5.7
・-5.6789 → -5.7
1 2 3 4 5 |
#sort_valuesメソッドで並び替え df15 = df11.sort_values('年間来店回数', ascending=False) df15[0:10].describe() 8.600000 |
第3問
列のデータを使用した演算やビニング処理が出題されます。
ほとんどの中小企業はやったことのない処理かと思います。
列のデータを列データを使って演算する
表「顧客別集計結果.csv」において、「合計購入額」を列「合計注文数」で割ることで得られる列「注文単価」を作成してください。
このとき、列「注文単価」の平均値は
です。
※ 回答は、小数(小数点以下1桁目までの精度)で記入してください。
仮に、小数点以下2桁目以降の桁まで数が続く場合は、小数第2位の数で四捨五入を行った結果を回答として記入してください。
四捨五入の例)
・0.1234 → 0.1
・5.6789 → 5.7
・-5.6789 → -5.7
1 2 3 4 5 6 7 8 9 |
df16 = pd.read_csv('/content/drive/MyDrive/マナビDX/顧客別集計結果.csv', encoding='cp932') #注文単価のカラムを追加 #注文単価のカラムにデータを追加 df17 = df16.assign(注文単価 = 0) df17['注文単価']=df17['合計購入額']/df17['合計注文数'] df17.describe() 8138.513226 |
順位付け
表「顧客別集計結果.csv」を、列「合計注文数」の値の大きさで順位付けを行ってください。
その後、上から3行分に該当する顧客の順位を求めましょう。(この際、行の並び順はダウンロード時の状態と同一であることを前提とします。)
1行目
位
2行目
位
3行目
位
※ ただし、順位付けは下記の規則で行います。
・順位は降順でつける。
・値が同一の場合、同順とする。
例. 点数が高い順にランク付けする場合
[Aさん: 76点, Bさん: 84点, Cさん: 76点] → [Aさん: 2位, Bさん: 1位, Cさん: 2位]
※ 回答は、整数で記入してください。
1 2 3 4 5 6 7 8 9 |
#rankメソッドで順位付け df18 = df17.rank(ascending=False,method='min') df18 顧客ID 合計購入額 合計注文数 従業員数 平均購入間隔日 注文単価 0 100.0 46.0 44.0 20.0 10.0 77.0 1 99.0 22.0 18.0 30.0 85.0 58.0 2 98.0 13.0 9.0 7.0 35.0 75.0 3 97.0 36.0 35.0 47.0 89.0 47.0 |
ビニング
表「顧客別集計結果.csv」において、列「平均購入間隔日」の値を3つのカテゴリ『4日未満』『4日以上6日未満』『6日以上』 にビニングしましょう。
このとき、各カテゴリ別に列「合計注文数」の平均値を求め、下の空欄に記述してください。
『4日未満』
『4日以上6日未満』
『6日以上』
※ 回答は、小数(小数点以下1桁目までの精度)で記入してください。
仮に、小数点以下2桁目以降の桁まで数が続く場合は、小数第2位の数で四捨五入を行った結果を回答として記入してください。
四捨五入の例)
・0.1234 → 0.1
・5.6789 → 5.7
・-5.6789 → -5.7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#cutメソッドで引数を指定してビニング処理 df19 = pd.cut(df17['平均購入間隔日'], [0,4,6,100], labels=['4日未満','4日以上6日未満','6日以上']) #ビニングしたものを確認 df20 = pd.DataFrame(df19) df20 = df20.rename(columns={'平均購入間隔日': 'ビニング'}) #ビニングしたデータを元のデータフレームに追加 #各カテゴリの統計値を算出 df22 = df17.assign(ビニング = 0) df22['ビニング']=df20['ビニング'] df221 = df22[df22["ビニング"] == "4日未満"] df222 = df22[df22["ビニング"] == "4-6"] df223 = df22[df22["ビニング"] == "6以上"] df221.describe() df222.describe() df223.describe() |
置換
表「顧客別集計結果.csv」において、列「合計購入額」には異常と思われるデータがあります。
そこで、下記のように修正を加えましょう。
・列「合計購入額」が10000以下の値は、10000以下を除いたデータの「合計購入額」の最小値に置換する
・列「合計購入額」が10000000以上の値は、10000000以上を除いたデータの「合計購入額」の最大値に置換する
上記の修正を加えた上で改めて列「合計購入額」の平均値を計算すると、答えは
になります。
※ 回答は、小数(小数点以下1桁目までの精度)で記入してください。
仮に、小数点以下2桁目以降の桁まで数が続く場合は、小数第2位の数で四捨五入を行った結果を回答として記入してください。
四捨五入の例)
・0.1234 → 0.1
・5.6789 → 5.7
・-5.6789 → -5.7
1 2 3 4 5 6 7 8 9 10 11 |
#「合計購入額」が10000以下の値は、10000以下を除いたデータの「合計購入額」の最小値に置換 df23 = df17.index[df17['合計購入額'] <= 10000] df23 = df17.drop(df23) df23.describe() 6.692000e+04 #「合計購入額」が10000000以上の値は、10000000以上を除いたデータの「合計購入額」の最大値に置換 df24 = df17.index[df17['合計購入額'] >= 10000000] df24 = df17.drop(df24) df24.describe() 3.256170e+06 |
1 2 3 4 5 |
#上記の修正を加えた上で改めて列「合計購入額」の平均値を計算 df24 = df17.mask(df17['合計購入額'] <= 10000,6.692000e+04) df25 = df24.mask(df24['合計購入額'] >= 10000000,3.256170e+06) df25.describe() 4.568377e+05 |
まとめ
pandasの基本知識から応用まで網羅的に知識を求められる問題が出題されています。
中小企業従事者にとっては非常に難しい問題が多いのですが、コツコツと学習を進めていきましょう。