LoginSignup
9

More than 1 year has passed since last update.

【Python】Altair でビッグデータを可視化する

Last updated at Posted at 2021-07-07

概要

グラフ可視化ライブラリ Altair は、pandas の DataFrame を入力することで様々なグラフを作成することができる。しかし、DataFrame の行数が 5000 を超えると次のようなエラーが起こる。

altair.utils.data.MaxRowsError: 
The number of rows in your dataset is greater than the maximum allowed (5000). 
For information on how to plot larger datasets in Altair, see the documentation

本稿では、関数型プログラミングライブラリ toolz を用いて、入力可能な最大行数を変更する方法を紹介する。

データの作成

前稿 と同様に、疑似乱数を用いて架空の学校で行われた期末試験の得点をテストデータとして用いる。この学校には学生が 10000 人在籍し、普通、特進、理数の 3 クラスが存在する。期末試験の科目は国語、数学、理科、社会、英語で各教科 100 点満点とする。

データの作成
import numpy as np
import pandas as pd

np.random.seed(1) # 乱数の固定

df = pd.DataFrame()

n = 10000 # 学生の人数
s = np.random.normal(55,10,n) # 学生の学力
c = np.random.randint(0,3,n) # クラス
s = s * (1 + c * 0.015) # クラスの学力差をつける
g = np.random.randint(0,2,n) # 性別

s1 = np.random.uniform(0.75,1.1,n) * s * (1 + g * 0.02)
s2 = np.random.uniform(0.9,1.1,n) * s * (1 - g * 0.05)

sex = ['男','女']
cl = ['普通','理数','特進']

df['学生番号'] = list(map(lambda x: 'ID'+str(x).zfill(5), range(1,1+n)))
df['国語'] = list(map(lambda x: round(x), s1))
df['数学'] = list(map(lambda x: round(x), s2))
df['クラス'] = list(map(lambda x: cl[x], c))
df['性別'] = list(map(lambda x: sex[x], g))
print(df)
  学生番号  国語  数学 クラス 性別
0     ID00001  63  80  特進  男
1     ID00002  44  48  理数  女
2     ID00003  48  43  普通  女
3     ID00004  46  40  特進  女
4     ID00005  55  63  普通  男
...       ...  ..  ..  .. ..
9995  ID09996  59  60  特進  男
9996  ID09997  53  59  普通  男
9997  ID09998  36  48  普通  男
9998  ID09999  58  54  特進  女
9999  ID10000  41  45  普通  男

[10000 rows x 5 columns]

toolz を用いたエラーの回避

以下のように toolzpipe で合成関数を作成する。関数内の max_rows で最大行数を指定すればよい。

demo.py
import altair as alt
from altair_saver import save
from altair import limit_rows, to_values
import toolz
t = lambda data: toolz.curried.pipe(data, limit_rows(max_rows=10000), to_values)
alt.data_transformers.register('custom', t)
alt.data_transformers.enable('custom')

scatter = alt.Chart(df).mark_circle(
        size=30
        ).encode(
        x=alt.X('国語',
            scale=alt.Scale(
                domain=[0,100]
                ),
            axis=alt.Axis(
                labelFontSize=15, 
                ticks=True, 
                titleFontSize=18, 
                title='国語の得点')
            ),
        y=alt.Y('数学',
            scale=alt.Scale(
                domain=[0, 100]
                ),
            axis=alt.Axis(labelFontSize=15, 
                ticks=True, 
                titleFontSize=18, 
                title='数学の得点')
            ),
        column=alt.Column('クラス',
            header=alt.Header(
                labelFontSize=15, 
                titleFontSize=18), 
            sort = alt.Sort(
                cl
                ), 
            title='クラス'
            ),
        color=alt.Color('性別', 
            scale=alt.Scale(
                domain=sex,
                range=['blue', 'red']
                ),
            ),
        tooltip=['国語', '数学'],
    ).properties(
        width=300,
        height=300,
        title="国語と数学の得点分布"
    ).interactive()

save(scatter,'scatter_10000.html',embed_options={'actions':True})

visualization (6).png

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9