記憶力が無い

プログラミングとランニングとカメラと何か

Plotly でディスク使用量の Sunburst Chart を作る

Plotly の練習がてら、ディスク使用量を Sunburst Chart で可視化してみました。

Plotlyとは

Plotly はチャートの生成等を行うためのグラフィックライブラリです。

今回使用するのは Python のライブラリ (plotly.py) ですが、チャート自体は HTML + JavaScript で出力されます。 直に JavaScript のライブラリ (plotly.js) を使ってチャートを書くこともできます。

ディスク使用量の計算

フォルダのサイズを次のように計算する

  • フォルダ内のファイル・フォルダを列挙し、次のように処理する
    • ファイルならそのサイズを加算
    • フォルダならそれに対し、この処理を再帰呼び出ししてサイズを計算し、サイズを加算

この処理を Python のコードに落とし込むと次のようになります。

import os

def f(current):
    total = 0
    if os.path.islink(current):
        return 0
    elif os.path.isfile(current):
        total = os.path.getsize(current)
    else:
        try:
            children = os.scandir(current)
        except:
            return 0
        for child in children:
            total += f(child.path)
    return total

f('c:\\')

ディスクのサイズが大きいと、この計算は数分かかる場合があります。

stackoverflow.com

フォルダのサイズを速く計算するのはなかなか難しいようです。

Sunburst Chart の作成

まずは適当な例を考えチャートを描画してみましょう。

hoge/
  ├ fuga/
  │  ├ fuga1.txt (5 MiB)
  │  └ fuga2.txt (10 MiB)
  └ piyo.txt (20 MiB)

このようなフォルダ構成の場合、ファイル・フォルダのサイズを表にすると次のようになります。

パス サイズ(MiB)
hoge/ 35
hoge/fuga/ 15
hoge/fuga/fuga1.txt 5
hoge/fuga/fuga2.txt 10
hoge/piyo.txt 20

この情報を Plotly の入力に変換していきます。

labels = []
parents = []
values = []

def add_data(path, parent, size):
    labels.append(path)
    parents.append(parent)
    values.append(size)

add_data('hoge/', '', 35)
add_data('hoge/fuga/', 'hoge/', 15)
add_data('hoge/fuga/fuga1.txt', 'hoge/fuga/', 5)
add_data('hoge/fuga/fuga2.txt', 'hoge/fuga/', 10)
add_data('hoge/piyo.txt', 'hoge/', 20)

Sunburst Chart の入力は labels, parents, values の3つです。

  • labels にはそのデータのラベルを指定します。チャートを表示したときにデータの部分にラベルが表示されます。
  • parents にはそのデータの親のラベルを指定します。どのラベルのデータがどのラベルの下に表示されるかをここで決めます。
  • values にはそのデータの値(今回はサイズ)を指定します。

このようにして作った入力を Plotly に突っ込みます。

https://plotly.com/python/sunburst-charts/

from plotly import graph_objects as go

trace = go.Sunburst(
    name='',
    labels=labels,
    parents=parents,
    values=values,
    branchvalues='total'
)

figure = go.Figure(
    data=trace
)

figure.show()

このコードを実行すると次のようなチャートが表示されます。

f:id:ttk1:20200731010121p:plain

ディスク使用量を Sunburst Chart 化

最初に示した関数では、親フォルダの情報が取れないのと、 labels, parents, values を記録する部分がないので、次のように修正します。

labels = []
parents = []
values = []

def f(current, parent):
    total = 0
    if os.path.islink(current):
        return 0
    elif os.path.isfile(current):
        total = os.path.getsize(current)
    else:
        try:
            children = os.scandir(current)
        except:
            return 0
        for child in children:
            total += f(child.path, current)

    labels.append(current)
    parents.append(parent)
    values.append(total / 1024 ** 3)

    return total

これで作ったデータを Plotly に突っ込みます。

私のCドライブで実行すると次のようになりました。

f:id:ttk1:20200731013058p:plain

これで、どこに大きなデータが保存されているか一発で見つけられますね!

コードの全体は下に置いてあります(※ 若干この記事で説明したコードから変更した箇所があります)。

github.com

Copyright © 2017 ttk1