web-dev-qa-db-ja.com

Pythonで有向グラフをプロットしますか?

私は、顧客の状態を移行するための有向グラフまたはSankeyダイアグラム(どれでも機能します)を作成しようとしています。データは以下のようになります。カウントは、現在の状態から次の状態に移行するユーザーの数を意味します。

**current_state         next_state          count**
New Profile              Initiated           37715
Profile Initiated          End               36411
JobRecommended             End                6202
New                        End                6171
ProfileCreated             JobRecommended     5799
Profile Initiated          ProfileCreated     4360
New                        NotOpted           3751
NotOpted                   Profile Initiated  2817
JobRecommended             InterestedInJob    2542
IntentDetected             ProfileCreated     2334
ProfileCreated             IntentDetected     1839
InterestedInJob            Applied            1671
JobRecommended             NotInterestedInJob 1477
NotInterestedInJob         ProfileCreated     1408
IntentDetected             End                1325
NotOpted                   End                1009
InterestedInJob            ProfileCreated     975
Applied                    IntentDetected     912
NotInterestedInJob         IntentDetected     720
Applied                    ProfileCreated     701
InterestedInJob            End                673

Sankeyを構築するコードを記述しましたが、プロットは簡単に読み取ることができません。読みやすい有向グラフを探しています。これが私のコードです:

    df = pd.read_csv('input.csv')

    x = list(set(df.current_state.values) | set(df.next_state))
    di = dict()

    count = 0
    for i in x:
        di[i] = count
        count += 1

    #
    df['source'] = df['current_state'].apply(lambda y : di[y])
    df['target'] = df['next_state'].apply(lambda y : di[y])


    #
    fig = go.Figure(data=[go.Sankey(
        node = dict(
          pad = 15,
          thickness = 20,
          line = dict(color = "black", width = 0.5),
          label = x,
          color = "blue"
        ),
        link = dict(
          source = df.source, 
          target = df.target,
          value = df['count']
      ))])


    #
    fig.update_layout(title_text="Sankey Diagram", font_size=10, autosize=False,
        width=1000,
        height=1000,
        margin=go.layout.Margin(
            l=50,
            r=50,
            b=100,
            t=100,
            pad=4
        ))
    fig.show()
5
NK09

これにより、次のことを前提として、基本的なSankey図が作成されます。

  1. データをstate_migration.csvというファイルに保存します
  2. ラベル(状態名)の空白をダッシュ​​/アンダースコア/なしに置き換えます
  3. 列間の空白をカンマで置き換えます
  4. Plotly、numpy、matplotlibがインストールされている

2と3は、先史時代以外のテキストエディター、またはpython自体、大量のデータの場合でも簡単に実行できます。引用符で囲まれていない値で空白を使用しないことを強くお勧めします。

結果

import plotly.graph_objects as go
import numpy as np
import matplotlib

if __name__ == '__main__':

  with open('state_migration.csv', 'r') as finput:
    info = [[ _ for _ in _.strip().lower().split(',') ]
                for _ in finput.readlines()[1:]]
  info_t = [*map(list,Zip(*info))] # info transposed

  # this exists to map the data to plotly's node indexing format
  index = {n: i for i, n in enumerate(set(info_t[0]+info_t[1]))}

  fig = go.Figure(data=[go.Sankey(
    node = dict(
      pad = 15,
      thickness = 20,
      line = dict(color = "black", width = 0.5),
      label = list(index.keys()),
      color = np.random.choice( list(matplotlib.colors.cnames.values()),
                                size=len(index.keys()), replace=False )
    ),
    link = dict(
      source = [index[_] for _ in info_t[0]],
      target = [index[_] for _ in info_t[1]],
      value = info_t[2]
  ))])

fig.update_layout(title_text="State Migration", font_size=12)
fig.show()

ノードをドラッグできます。位置を事前に定義したり、他のパラメーターを確認したりする場合は、 this を参照してください。

私が使用したデータは、あなたの入力のクリーンなバージョンでした:

currentstate,next_state,count
new,initiated,37715
profileinitiated,end,36411
jobrecommended,end,6202
new,end,6171
profilecreated,jobrecommended,5799
profileinitiated,profilecreated,4360
new,notopted,3751
notopted,profileinitiated,2817
jobrecommended,interestedinjob,2542
intentdetected,profilecreated,2334
profilecreated,intentdetected,1839
interestedinjob,applied,1671
jobrecommended,notinterestedinjob,1477
notinterestedinjob,profilecreated,1408
intentdetected,end,1325
notopted,end,1009
interestedinjob,profilecreated,975
applied,intentdetected,912
notinterestedinjob,intentdetected,720
applied,profilecreated,701
interestedinjob,end,673

ダイアグラムが奇妙だったので、「新しいプロファイル」を既存の状態「新しい」に変更しました。必要に応じて自由に調整してください。

私が使用したライブラリーは、あなたが望むものに絶対に必要というわけではありません。私はそれらに慣れているだけです。有向グラフについては、Roland Smithがカバーしています。また、Plotlyを使用して行うこともできます。その gallery を参照してください。

  • Plotlyに代わるもの、優先順に:matplotlib、seaborne、ggplot、raw dot/graphviz
  • matplotlibは、事前定義された16進数の色のリストを提供するためにここでのみ使用されました
  • numpyは、置換なしでリストからランダムな値を選択するためにのみ使用されました(この場合は色)

Python 3.8.1でテスト済み

1
condekind

condekindは答えがカバーされているように見えますが...パンダを使用しているので、これらの以前の答えは、データを整理して図を作成する実用的な側面に役立ちます。

pandas dataframe? を使用してサンキーダイアグラムの構造を定義する方法

データフレームからSankey図を描画

および alishobeiri には、使用できるいくつかの便利な例とコードがあります。 https://plot.ly/~alishobeiri/1591/plotly-sankey-diagrams/#/

plot.ly documentation とともに、ノード配置の特定の質問に答えます。

Sankey図が散らかっている場合は、水平方向ではなく垂直方向を試すこともできます。

0
Ali F