【最短で理解する】データ分析のためのPython基礎

# はじめに
Pythonを使ってデータ分析をしてみたい...とか、ゼミや研究でPythonを使うことになったけどプログラミングやったことない...という方へ。
**これさえわかればとりあえず基礎は大丈夫です** （多分）。知識のおさらいに使うのもありだと思います。
まず、汎用的なPythonの文法の基礎を最小限扱ってから、データ分析に用いる基本的な道具やテクニックについて記載しています。
Pythonの基本的な文法について知ってる人は[２. データ分析のためのPython基礎](#２-データ分析のためのpython基礎)まで飛んでもらってOKです。


この記事は2019年度に大学のゼミのメンバーにPythonを教えるのに使った資料を元に修正・追加したものです。（別のとある私立大学の講義にも採用していただきました！！）

あくまでデータ分析を行うためのPythonの基礎なので、データ分析そのものについてはあまり言及してません。もっと学びたい方には[おすすめ書籍](#3-さらに学びたい人へ)を最後に紹介します。

# 実行環境の準備
初めてプログラミングをすると躓きがちなのはプログラミングをするための環境構築ですが、Google Colaboratoryを用いることでちゃちゃっとPythonを使えるようにします。
GoogleDriveを開いて、Colaboratoryをインストールします。
<img width="1166" alt="Screenshot at May 05 17-07-08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445029/619939a4-cdaa-84b4-538d-58432a8a0cda.png">

以下、Google Colaboratoryでの実行を前提としますが、実行環境が整っている方はjupyter等ご自身の環境で実施いただければと思います。

# 1. Python文法基礎
まずは、Pythonの基礎から。
## 1.1 文字を画面に表示させてみる
print関数を用います。

```python
print("Hello World!")
```
```:出力
Hello World!
```

## 1.2 四則演算
```python
3 + 4 #足し算
#出力: 7

8 - 3 #引き算
#出力: 5

9 * 3 #掛け算
#出力: 27

9 / 3 #割り算
#出力: 3.0

5 // 2 #割り算の商
#出力: 2

5 % 2 #割り算の余り
#出力: 1

5 ** 2 #累乗
#出力: 25

```
## 1.3 変数の扱い(整数型・浮動小数点型)
Pythonのデータ型について知りましょう。データ型とは、文字通りデータの型のことです。と言ってもピンとこないかもしれません。
習うより慣れろってことで、よく用いられるデータ型についていくつかみてみましょう。

```python
a = 4
a
#出力: 4
```

ちなみに、文字としてのaを表示させたい場合には

```python
print('a')
#出力： a
```
```python
b = 1.2
b #出力:1.2

a + b
#aは「整数型」、bは「浮動小数点型」
#出力:5.2
```
「=」は等価ではなく代入を意味します。

```python
a = a + 1
a #出力:5
```

```python
c = 2
c += 1 #二項演算子 c = c + 1 と同じこと
c #出力： 3
```

```python
d = 6
d -= 1 #二項演算子 c = c - 1 と同じこと
d
```

```python
e = 100*5
e #出力：５００
```
```python
f = 4
f == 4 #出力：True
#「==」は比較演算子。代入によりfは4であることは正しいのでTrue

f == 5 #出力：False
```
### Pythonでのプログラムの書き方で注意    
Pythonでは字下げ(インデント)がプログラムとして意味を持ちます。  
意味もなく字下げをするとエラー。

```python
x = 1
 x = x + 1
x
```

```python:出力
  File "<ipython-input-92-80d18cdaadaa>", line 2
    x = x + 1
    ^
IndentationError: unexpected indent
```

## 1.4 文字列型
文字列型のデータはシングルクォーテーションあるいはダブルクォーテーションで文字列を囲むことで作成

```python
a = "データ分析"
b = 'Python'
a,b
```
```python:出力
('データ分析', 'Python')
```
文字列をつなげてみます。+を用います。

```python
a = "データ分析のための"
b = 'Python基礎'
a + b
```
```python：出力
'データ分析のためのPython基礎'
```
以下の場合はエラーとなります。

```python
c = "4" #文字列型
d = 3 #整数型
c + d #変数の型が違うのでエラー
```
```python:出力
TypeError                                 Traceback (most recent call last)
<ipython-input-98-237326ccb44f> in <module>()
      1 c = "4" #文字列型
      2 d = 3 #整数型
----> 3 c + d #変数の型が違うのでエラー

TypeError: must be str, not int
```
文字列の長さ（文字数）の取得にはlen（）関数を用いる

```python
a = "DataAnalytics"
len(a) #出力：13
```
## 1.5 メソッド
データ型ごとに使える関数と思ってください。
単独で使える普通の関数と違い、メソッドは変数や値に付けて呼び出します。
文字列型で使えるメソッドを少し使ってみましょう。

```python
name = 'Donald Trump'

#アルファベットを全て大文字にするupperメソッド
print(name.upper())

#アルファベットを全て小文字にするlowerメソッド
print(name.lower())
```

```python:出力
DONALD TRUMP
donald trump
```
## 1.6 リスト型
数値や文字列などを並べて格納できるデータ型。文字や文字列などを、カンマで区切って並べる。
かたまりのデータをまとめて扱うときに便利。

```python
L = [1,2,3,4]
L
```
```python:出力
[1, 2, 3, 4]
```
順番が最初のデータは「0番目」となります。

```python
L[1] #2番目の要素を取得
#出力：2
L[:] #全要素を取得
#出力：[1, 2, 3, 4]
```
内容の変更は代入で行います。

```python
L[2]=999 #3番目の要素を変更
L  #出力：[1, 2, 999, 4]
```
データの追加にはappendメソッドを用います。

```python
L.append(30) #リストの末尾に30を追加
L #出力：[1, 2, 999, 4, 30]
```
###リストのスライス
データの間に「仕切り」があり、その仕切りの番号を指定すると考えるとわかりやすい。

```python
arashi = ["櫻井翔","松本潤","大野智","相葉雅紀","二宮和也"]
print(arashi[0:1])
print(arashi[1:4])
print(arashi[2:2])
```
```python:出力
['櫻井翔']
['松本潤', '大野智', '相葉雅紀']
[]
```
### 練習問題
arashiリストから、相葉ちゃんとニノだけリストから取り出し表示させよう。
### 解答
```python
print(arashi[3:5])
#出力:['相葉雅紀', '二宮和也']
```

## 1.7 辞書型 
辞書では、見出し語 (キー) と対応する要素である 値(value)を紐づけて対応関係を管理します。

```python
arashi = {'櫻井翔':'38','松本潤':'36','大野智':'39'}
print(arashi)
```
```python:出力
{'櫻井翔': '38', '松本潤': '36', '大野智': '39'}
```
キーを指定することでそのキーに紐づく値を取得します。

```python
arashi["大野智"] #キーで参照
#出力:'39'
```
## 1.8 タプル型

```python
a = (1,2,3,4)
a #出力：(1,2,3,4)
```
```python
print(a[0]) #出力：1
```
リスト型との違いはイミュータブル（変更不可能）である点。
変更されたら困るデータを管理するのに便利。

```python
a[1]=10
#変更できないのでエラー
```
```python:出力
TypeError                                 Traceback (most recent call last)
<ipython-input-130-5434a1e381e3> in <module>()
----> 1 a[1]=10
      2 #変更できないのでエラー

TypeError: 'str' object does not support item assignment
```
## 1.9 制御構造
### if文
条件に従って動作を指定します。
以下では変数が20以上（age>=20がTrue）なら「20歳以上だね」、そうでなければ（else）「未成年だね」を返します。
コロンのあとはキーボードのTabキーでインデントを付けてください。

```python
age = 20
if age >= 20:
  print('20歳以上だね')
else:
  print('未成年だね')

#出力： 20歳以上だね
```
```python
age = 20
if age >= 20:
print('20歳以上だね') #インデントがないのでエラー
else:
print('未成年だね')
```
```python:出力
  File "<ipython-input-154-b2f09d489829>", line 4
    print('20歳以上だね')
        ^
IndentationError: expected an indented block
```
### for文<br>
繰り返し処理を実行します。こちらもコロンのあとはインデントを付けます。

```python
for i in range(5):  #0から数えて５回繰り返し
  print(i)

#出力
0
1
2
3
4
```

## 1.10 関数定義
自分の関数を作っちゃおう。
defで定義の宣言をし、関数名（この場合はf（））と変数を定義します。コロン以下に関数の挙動をプログラムします。

```python
def f(x,y):
  return x**2 + y**2 # 戻り値を返す（計算結果が渡される）

print(f(10,20)) #１０の二乗＋２０の二乗
#出力:500
```

## 1.11 FizzBuzz問題
3の倍数で’Fizz'、5の倍数で'Buzz'、3と5の公倍数で'FizzBuzz'、
それ以外の数でそのまま数を表示させるプログラムをつくってみます。
条件を加える場合はelifを用います。

```python
for i in range(1,31):
  if i%3 == 0 and i%5==0:
    print('FizzBuzz')
  elif i%3 == 0:
    print('Fizz')
  elif i%5 == 0:
    print('Buzz')
  else:
    print(i)
```

```python:出力
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
```
### 練習問題
引数に数字を入れると、上記のFizzBuzzのルールで数字が表示される関数を作ろう。
また実際にその関数で表示を確かめてみよう。
### 解答

```python
def FizzBuzz(i):
  if i%3 == 0 and i%5 == 0:
    print('FizzBuzz')
  elif i%3 == 0:
    print('Fizz')
  elif i%5 == 0:
    print('Buzz')
  else:
    print(i)

FizzBuzz(100)
#出力：Buzz
FizzBuzz(105)
#出力：FizzBuzz
```
## 1.12 モジュール
Pythonは関数のような機能をまとめ、必要な時に読み込んで使える**モジュール**という仕組みを持っています。
ここまでで使った関数はPythonに内蔵されているいつでも使える関数で、これらを**組み込み関数**と呼びます。http://docs.python.jp/3/library/functions.html  にその一覧があります。

一方、限られた用途で使うものはモジュールから読み込むことで使えるようになります。
Pythonにはこの便利なモジュールがたくさん付属しているのですが、このPythonに付属のモジュールの集合体のことを**標準ライブラリ**といいます。
ちなみに、Anacondaには標準ライブラリの他にも便利なライブラリが付属しています。


```python
import math #mathモジュールを読みこむ（インポート）
math.cos(0) #出力：1.0
```
**モジュール名.関数名**  のようにモジュール名と関数名を. でつなげて使う

```python
import numpy as np #NumPyモジュールをnpという名前でインポート
```

```python
#円周率π
np.pi #出力：3.141592653589793

#cos(180°)
math.cos(np.pi) #出力：-1.0
```
# ２. データ分析のためのPython基礎
 
## データ分析でよく使われるライブラリの一例と主な用途
Numpy ： 数値計算、行列演算
Pandas：データの操作、演算
Matplotlib : グラフの描画
他にもいろんなライブラリがありますが、今回はこの３つについて解説します。

## 2.1 Numpyでベクトルや行列の計算
Numpyは数値計算のためのライブラリです。行列の演算をしてみましょう。

```python
import numpy as np #NumPyモジュールをインポートし、'np'として用いる
arr1 = np.array([1,4,3]) #1×3行列の作成
arr1
```

```python:出力
array([1, 4, 3])
```
```python
arr1[2] #要素の取得
#出力：3
```

```python
#2×3行列
arr2 = np.array([[1,2,3],[4,5,6]])
```
```python:出力
array([[1, 2, 3],
       [4, 5, 6]])
```

```python
arr2[1,1] #要素の取得
#出力：5

arr2.shape
#出力：(2, 3)

arr1 + arr2 #行列の足し算
#出力：
array([[2, 6, 6],
       [5, 9, 9]])
```
dot()関数で行列の積を計算してみましょう

```python
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
np.dot(a,b)

#出力
array([[19, 22],
       [43, 50]])
```
できる方は手計算して、行列の積の結果が一致するかどうか確認してみましょう。
ちなみにさっきの行列（arr1,arr2）の積は、、

```python
np.dot(arr1,arr2) 
```
```python:出力
ValueError                                Traceback (most recent call last)
<ipython-input-62-e5b6075b8937> in <module>()
----> 1 np.dot(arr1,arr2)

<__array_function__ internals> in dot(*args, **kwargs)

ValueError: shapes (3,) and (2,3) not aligned: 3 (dim 0) != 2 (dim 0)
```
arr1の列数とarr2の行数が一致せず、行列の積が定義できないのでエラーです。

## 2.2 Matplotlibでグラフ描画
描画にはデータ可視化のためのライブラリであるMatplotlibを使います。
今回は、Matplotlibライブラリのpyplotモジュールをimportし、pyplotモジュール内のplot関数を用います。
まずは直線を描いてみましょう。
措定した範囲を分割した点を複数用意し、それらを線で結ぶイメージです。

```python
import matplotlib.pyplot as plt
# Matplotlibパッケージのpyplotモジュールをインポート
import numpy as np

x = np.linspace(0,10,100) # 変数xにNumPyの関数linspaceを使用し0から10までの数字を100分割したものを代入
y = x

plt.plot(x,y) #xとyをプロット
plt.show() #グラフを表示
```
![line.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445029/08716dbb-09f5-fe06-958d-4d8abe61fdd5.png)
次は2次曲線を描いてみます。
また、matplotlibで日本語フォントを使うためのライブラリ（japanize-matplotlib）をインストールしてimportで呼び出せるようにします。

```
!pip install japanize-matplotlib
```
```python
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib

x = np.linspace(-5,5,300) #変数xにNumPyの関数linspaceを使用し-5から5までの数字を300分割したものを代入
y = x**2

plt.plot(x,y,color = "r") #色を赤に指定
plt.xlabel('y=x^2のグラフ') #x軸のラベルを設定
plt.show()
```
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445029/fdee166e-b957-cff2-6cdf-0ebf73a7ead7.png)
最初の直線の描画の際にも書いたように、滑らかな曲線のように見えるこの放物線は実際は直線の集合です。
分割を粗くしてみましょう。

```python
x = np.linspace(-5,5,10) #１０分割にしてみる
y = x**2

plt.plot(x,y,color = "r")
plt.xlabel('y=x^2のグラフ')
plt.show()
```
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445029/16fcd71a-9475-8a47-8022-1670b9783903.png)
さっきより少しカクカクしていますね。
もうちょっとグラフを練習しましょう。次はNumpyの関数を用いて三角関数のグラフ描画します。

```python
import math
x = np.linspace(-np.pi, np.pi) #-πからπまで
plt.plot(x, np.cos(x), color='r', ls='-', label='cos') #線の種類や色、ラベルを指定
plt.plot(x, np.sin(x), color='b', ls='-', label='sin')
plt.plot(x, np.tan(x), color='c', marker='s', ls='None', label='tan')

#表示する座標の範囲を指定
plt.xlim(-np.pi, np.pi) 
plt.ylim(-1.5, 1.5)

#x=0とy=0に補助線を引く
plt.axhline(0, ls='-', c='b', lw=0.5) #horizontal(水平)だからhline
plt.axvline(0, ls='-', c='b', lw=0.5) #vertical(垂直)だからvline

plt.legend()
plt.xlabel('ｘ軸')
plt.ylabel('ｙ軸')
plt.title('三角関数のグラフ')

plt.show()
```
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445029/39a6d039-d200-bea0-e11c-3545cb2c317b.png)

## 2.3 Pandasでデータ操作

データの前処理は主にこのPandasを使います。分析対象のデータをDataFrame（データの格納庫のようなもの）に保存し、必要に応じて加工します。<br>
分析に使えるデータはいつも綺麗だとは限りません。
データ分析や機械学習で費やす時間のほとんどはこの前処理です。前処理を制するものがデータ分析を制します。まずは、簡単なDataFrameを２つ作成してみましょう。

```python
import pandas as pd
df1 = pd.DataFrame({
          '名前':['sato','ito','kato','endo','naito'],
          '学生番号':[1,2,3,4,5],
          '体重':[92,43,58,62,54],
          '身長':[178,172,155,174,168]
          })
df1
```

|    | 名前   |   学生番号 |   体重 |   身長 |
|---:|:-------|-----------:|-------:|-------:|
|  0 | sato   |          1 |     92 |    178 |
|  1 | ito    |          2 |     43 |    172 |
|  2 | kato   |          3 |     58 |    155 |
|  3 | endo   |          4 |     62 |    174 |
|  4 | naito  |          5 |     54 |    168 |

DataFrameにはインデックスが付与されます（0から始まる一番左の数字）

```python
df2 = pd.DataFrame({
          '学生番号':[1,2,3,5,6,9],
          '数学':[50,60,70,80,90,100],
          '英語':[95,85,80,75,70,65],
          '理科':[40,55,60,65,50,75],
          'クラス':['A組','B組','A組','C組','B組','C組']
          })
df2
```
|    |   学生番号 |   数学 |   英語 |   理科 | クラス   |
|---:|-----------:|-------:|-------:|-------:|:---------|
|  0 |          1 |     50 |     95 |     40 | A組      |
|  1 |          2 |     60 |     85 |     55 | B組      |
|  2 |          3 |     70 |     80 |     60 | A組      |
|  3 |          5 |     80 |     75 |     65 | C組      |
|  4 |          6 |     90 |     70 |     50 | B組      |
|  5 |          9 |    100 |     65 |     75 | C組      |

２つのデータフレームを作成しました。
df1には名前と体重などの情報、df2には成績などの情報が格納されています。また、２つのデータフレームは一意の学生番号で紐づいているとします。

### データの抽出
特定の列を呼び出す際は[ ]で列名を指定します。

```python
df2['数学']
```
```:出力
0     50
1     60
2     70
3     80
4     90
5    100
Name: 数学, dtype: int64
```
複数列を抽出する際は[ ]を二重にして呼び出します。

```python
df2[['英語','クラス']]
```
|    |   英語 | クラス   |
|---:|-------:|:---------|
|  0 |     95 | A組      |
|  1 |     85 | B組      |
|  2 |     80 | A組      |
|  3 |     75 | C組      |
|  4 |     70 | B組      |
|  5 |     65 | C組      |
### ソート

まずは特定のカラムだけソート（並び替え）します。
sort_values()関数を用います。デフォルトでは昇順となります。

```python
df1['身長'].sort_values()
#出力:
2    155
4    168
1    172
3    174
0    178
Name: 身長, dtype: int64
```
体重でソートしてdf1全体を表示する場合はsort_values()関数のbyの引数を設定します。

```python
df1.sort_values(by=["体重"], ascending=False) #ascending=True　なら昇順
```
|    | 名前   |   学生番号 |   体重 |   身長 |
|---:|:-------|-----------:|-------:|-------:|
|  0 | sato   |          1 |     92 |    178 |
|  3 | endo   |          4 |     62 |    174 |
|  2 | kato   |          3 |     58 |    155 |
|  4 | naito  |          5 |     54 |    168 |
|  1 | ito    |          2 |     43 |    172 |

体重について降順に並んでます。

### データの結合
merge関数を用いると、いろんな種類のデータ結合ができます。
df1とdf2を学生番号をキーに結合させてみます。
#### 内部結合（inner join）

```python
data_inner = pd.merge(df1,df2, on='学生番号', how='inner')
data_inner
```
|    | 名前   |   学生番号 |   体重 |   身長 |   数学 |   英語 |   理科 | クラス   |
|---:|:-------|-----------:|-------:|-------:|-------:|-------:|-------:|:---------|
|  0 | sato   |          1 |     92 |    178 |     50 |     95 |     40 | A組      |
|  1 | ito    |          2 |     43 |    172 |     60 |     85 |     55 | B組      |
|  2 | kato   |          3 |     58 |    155 |     70 |     80 |     60 | A組      |
|  3 | naito  |          5 |     54 |    168 |     80 |     75 |     65 | C組      |

２つのデータフレームに共通するデータのみ結合されました。
ちなみに、df1とdf2は共通するカラムが学生番号のみなので、わざわざ指定しなくてもデフォルトで学生番号がキーとなります。

#### 外部結合（outer join）

```python
data_outer = pd.merge(df1, df2, how = 'outer')
data_outer
```
|    | 名前   |   学生番号 |   体重 |   身長 |   数学 |   英語 |   理科 | クラス   |
|---:|:-------|-----------:|-------:|-------:|-------:|-------:|-------:|:---------|
|  0 | sato   |          1 |     92 |    178 |     50 |     95 |     40 | A組      |
|  1 | ito    |          2 |     43 |    172 |     60 |     85 |     55 | B組      |
|  2 | kato   |          3 |     58 |    155 |     70 |     80 |     60 | A組      |
|  3 | endo   |          4 |     62 |    174 |    nan |    nan |    nan | nan      |
|  4 | naito  |          5 |     54 |    168 |     80 |     75 |     65 | C組      |
|  5 | nan    |          6 |    nan |    nan |     90 |     70 |     50 | B組      |
|  6 | nan    |          9 |    nan |    nan |    100 |     65 |     75 | C組      |

outer joinの場合はどちらかのデータフレームにしか存在しないものも取得します。
#### 左外部結合(left join)

```python
data_left = pd.merge(df1,df2,how = 'left')
data_left
```
|    | 名前   |   学生番号 |   体重 |   身長 |   数学 |   英語 |   理科 | クラス   |
|---:|:-------|-----------:|-------:|-------:|-------:|-------:|-------:|:---------|
|  0 | sato   |          1 |     92 |    178 |     50 |     95 |     40 | A組      |
|  1 | ito    |          2 |     43 |    172 |     60 |     85 |     55 | B組      |
|  2 | kato   |          3 |     58 |    155 |     70 |     80 |     60 | A組      |
|  3 | endo   |          4 |     62 |    174 |    nan |    nan |    nan | nan      |
|  4 | naito  |          5 |     54 |    168 |     80 |     75 |     65 | C組      |

left joinでは結合先(df1)に存在するものは残ります。inner joinの時とは違い、欠損値を含めてendoさんのデータが表示されています。
#### 右外部結合 (right join)

```python
data_right = pd.merge(df1,df2,how = 'right')
data_right
```
|    | 名前   |   学生番号 |   体重 |   身長 |   数学 |   英語 |   理科 | クラス   |
|---:|:-------|-----------:|-------:|-------:|-------:|-------:|-------:|:---------|
|  0 | sato   |          1 |     92 |    178 |     50 |     95 |     40 | A組      |
|  1 | ito    |          2 |     43 |    172 |     60 |     85 |     55 | B組      |
|  2 | kato   |          3 |     58 |    155 |     70 |     80 |     60 | A組      |
|  3 | naito  |          5 |     54 |    168 |     80 |     75 |     65 | C組      |
|  4 | nan    |          6 |    nan |    nan |     90 |     70 |     50 | B組      |
|  5 | nan    |          9 |    nan |    nan |    100 |     65 |     75 | C組      |

left joinと同様に、結合先(今度はdf2)のデータは残されます。outer joinの時とは違い、endoさんのデータは表示されません。
それぞれの結合の違いについてよく理解できましたか？

### カラムの追加
df2で、理系科目の合計点を表すカラムを追加しましょう。
以下のように新しいカラム名を指定して代入すればOKです。

```python
df2['理系科目'] = df2['数学'] + df2['理科']
df2 
```
|    |   学生番号 |   数学 |   英語 |   理科 | クラス   |   理系科目 |
|---:|-----------:|-------:|-------:|-------:|:---------|-----------:|
|  0 |          1 |     50 |     95 |     40 | A組      |         90 |
|  1 |          2 |     60 |     85 |     55 | B組      |        115 |
|  2 |          3 |     70 |     80 |     60 | A組      |        130 |
|  3 |          5 |     80 |     75 |     65 | C組      |        145 |
|  4 |          6 |     90 |     70 |     50 | B組      |        140 |
|  5 |          9 |    100 |     65 |     75 | C組      |        175 |

### 集計関数
クラスごとでテストの平均点を知りたいとします。groupby関数を用います。
以下では、クラスごとに集計したあと、mean関数で平均をとっています。

```python
df2[['数学','英語','理科','クラス']].groupby(['クラス']).mean().reset_index() 
#インデックスをリセット（表のずれがなくなる）
```
| クラス   |   数学 |   英語 |   理科 |
|:---------|-------:|-------:|-------:|
| A組      |     60 |   87.5 |   50   |
| B組      |     75 |   77.5 |   52.5 |
| C組      |     90 |   70   |   70   |

groupbyで集計し、そのあとの関数でグループごとに演算します。
mean関数の他にも、max関数、median関数、min関数なども使えます。

```python
# 各クラスの科目別最低点を抽出
df2[['数学','英語','理科','クラス']].groupby(['クラス']).min().reset_index() 
```
| クラス   |   数学 |   英語 |   理科 |
|:---------|-------:|-------:|-------:|
| A組      |     50 |     80 |     40 |
| B組      |     60 |     70 |     50 |
| C組      |     80 |     65 |     65 |

### CSV出力
作成したデータフレームをcsv形式で出力するには、to_csv関数を用います。

```python
data_right.to_csv('sample.csv')
```

### CSVデータの読み込み
今回はDataFrameを一から作りましたが、本来はcsv形式でデータを読み込む場面が多いです。
CSV形式のファイルをpandasで読み込むには read_csv() 関数を使います。
ただしこれはカンマ区切りのcsvの場合に使用します。タブ区切りの場合は read_table() 関数を使用します。
先ほど出力したsample.csvを読み込んで、改めてDataFrameとして表示してみましょう。

```python
sample = pd.read_csv('sample.csv', index_col=0) #indexは無視
sample
```
|    | 名前   |   学生番号 |   体重 |   身長 |   数学 |   英語 |   理科 | クラス   |
|---:|:-------|-----------:|-------:|-------:|-------:|-------:|-------:|:---------|
|  0 | sato   |          1 |     92 |    178 |     50 |     95 |     40 | A組      |
|  1 | ito    |          2 |     43 |    172 |     60 |     85 |     55 | B組      |
|  2 | kato   |          3 |     58 |    155 |     70 |     80 |     60 | A組      |
|  3 | naito  |          5 |     54 |    168 |     80 |     75 |     65 | C組      |
|  4 | nan    |          6 |    nan |    nan |     90 |     70 |     50 | B組      |
|  5 | nan    |          9 |    nan |    nan |    100 |     65 |     75 | C組      |

ここまでで、Pythonでデータ分析をする際の基本的な操作は一通り学ぶことができました。
最後に、練習問題を解いてみましょう。

## 練習問題
df2のデータを用いて、クラスごとで科目の合計点の平均を求め、それを棒グラフで図示してください。
※ヒント：棒グラフの描画にはmatplotlib.pyplotのbar関数を用います。
## 解答例
```python
import matplotlib.pyplot as plt
import japanize_matplotlib

df2['合計点'] = df2['数学'] + df2['英語'] +df2['理科']
sum_score = df2[['クラス','合計点']].groupby(['クラス']).mean().reset_index()

x = sum_score['クラス']
y = sum_score['合計点']
plt.bar(x,y)

plt.xlabel('クラス')
plt.ylabel('平均合計点')
plt.title('クラス別平均合計点')
plt.show()
```
![average.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445029/1bf9a074-7b32-d108-32d7-618b82ed6bbc.png)
試験の合計点の平均はC組が一番高いですね。

#3. さらに学びたい人へ
ここまで何気に長くなってしまいました。取り組んでくれた方、お疲れ様です。
もっと深めたい人には以下の本をオススメします。

### Pythonについてもっと知りたい人
<a target="_blank" href="https://www.amazon.co.jp/gp/product/B01NCOIC2P/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B01NCOIC2P&linkCode=as2&tag=yuto10-22&linkId=3760e8df4eebdcda3cfea97975dba246">みんなのPython 第4版</a>
基本をマスターした後に読むといいでしょう。辞書的に使うのも○です。

### Pythonでのデータ分析をもっと深めたい人
[Pythonによるデータ分析入門 第2版 ―NumPy、pandasを使ったデータ処理](https://www.amazon.co.jp/Python%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E2%80%95NumPy%E3%80%81pandas%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E5%87%A6%E7%90%86-Wes-McKinney/dp/487311845X/)

### データの前処理に強くなりたい人
[前処理大全［データ分析のためのSQL/R/Python実践テクニック］](https://www.amazon.co.jp/%E5%89%8D%E5%87%A6%E7%90%86%E5%A4%A7%E5%85%A8%EF%BC%BB%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AESQL-R-Python%E5%AE%9F%E8%B7%B5%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF%EF%BC%BD-%E6%9C%AC%E6%A9%8B-%E6%99%BA%E5%85%89-/dp/B07C3JFK3V/)
実務でよく参照します。Python以外にも、RのdplyrやSQLでの前処理についても学べます。

[Python実践データ分析100本ノック](https://www.amazon.co.jp/Python%E5%AE%9F%E8%B7%B5%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90100%E6%9C%AC%E3%83%8E%E3%83%83%E3%82%AF-%E4%B8%8B%E5%B1%B1-%E8%BC%9D%E6%98%8C/dp/4798058750/r8674263&s=books&sr=1-1)
名前に「データ分析」とありますが、pandasによるデータの前処理について多くページが割かれています。**データ分析は前処理が8割という事実**（？）に即した書籍といえます。
pandasの基本的な操作はこれで十分身に付けられます。

### Pythonで機械学習をやってみたい人
オライリーの機械学習本２冊を紹介します。

[Pythonではじめる機械学習 ―scikit-learnで学ぶ特徴量エンジニアリングと機械学習の基礎](https://www.amazon.co.jp/Python%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92-%E2%80%95scikit-learn%E3%81%A7%E5%AD%A6%E3%81%B6%E7%89%B9%E5%BE%B4%E9%87%8F%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%A8%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%81%AE%E5%9F%BA%E7%A4%8E-Andreas-C-Muller/dp/4873117984/)

[Python機械学習クックブック](https://www.amazon.co.jp/Python%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%82%AF%E3%83%83%E3%82%AF%E3%83%96%E3%83%83%E3%82%AF-Chris-Albon/dp/4873118670/)

### 機械学習のアルゴリズムの仕組みを勉強したい人
[機械学習のエッセンス -実装しながら学ぶPython,数学,アルゴリズム](https://www.amazon.co.jp/%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%81%AE%E3%82%A8%E3%83%83%E3%82%BB%E3%83%B3%E3%82%B9-%E5%AE%9F%E8%A3%85%E3%81%97%E3%81%AA%E3%81%8C%E3%82%89%E5%AD%A6%E3%81%B6Python-%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0-Machine-Learning/dp/4797393963/)
代表的な機械学習のアルゴリズムについて、一からPythonで実装します。機械学習に用いる数学についても学べます。