1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

未接続ノードがあってもOK!重み付きエッジリストから隣接行列を生成する関数の実装

Posted at

user:

辺が [('node_name1', 'node_name2'), ('node_name1', 'node_name3'), ...] のような形で入力されたとき、隣接行列を pandas dataframe として返す関数を書いてください。

assistant:

以下は、辺リスト edges = [('node_name1', 'node_name2'), ('node_name1', 'node_name3'), ...] から 隣接行列を pandas の DataFrame 形式で返す関数です。

import pandas as pd

def edges_to_adjacency_matrix(edges, directed=False):
    """
    辺リストから隣接行列(pandas DataFrame)を作成する。
    
    Parameters:
    - edges: list of tuple (node1, node2)
    - directed: 有向グラフなら True, 無向グラフなら False

    Returns:
    - pandas.DataFrame: 隣接行列
    """
    # ノードの集合を取得
    nodes = sorted(set([n for edge in edges for n in edge]))
    
    # 隣接行列を初期化(すべて0)
    adj_matrix = pd.DataFrame(0, index=nodes, columns=nodes)

    # エッジに従って1を設定
    for src, dst in edges:
        adj_matrix.loc[src, dst] = 1
        if not directed:
            adj_matrix.loc[dst, src] = 1

    return adj_matrix

使用例:

edges = [('A', 'B'), ('A', 'C'), ('B', 'C')]
adj_matrix = edges_to_adjacency_matrix(edges)
print(adj_matrix)

出力(無向グラフの場合):

   A  B  C
A  0  1  1
B  1  0  1
C  1  1  0

必要に応じて、有向・無向の指定や、重み付きなども拡張できます。ご希望があれば対応します!

user:

どういたしまして!
重み付きエッジに対応するように関数を改良します。
エッジは次のような形式になります:

edges = [('A', 'B', 2.0), ('A', 'C', 3.5), ...]

このとき、隣接行列の値は 0 の代わりに重みになります。


✅ 重み付きに対応した関数:

import pandas as pd

def weighted_edges_to_adjacency_matrix(edges, directed=False):
    """
    重み付きの辺リストから隣接行列(pandas DataFrame)を作成する。
    
    Parameters:
    - edges: list of tuple (node1, node2, weight)
    - directed: 有向グラフなら True, 無向グラフなら False

    Returns:
    - pandas.DataFrame: 隣接行列(値は重み、辺がなければ0)
    """
    # ノードの集合を取得
    nodes = sorted(set([n for edge in edges for n in edge[:2]]))

    # 隣接行列を初期化(全て0.0)
    adj_matrix = pd.DataFrame(0.0, index=nodes, columns=nodes)

    # エッジに従って重みを設定
    for src, dst, weight in edges:
        adj_matrix.loc[src, dst] = weight
        if not directed:
            adj_matrix.loc[dst, src] = weight

    return adj_matrix

使用例:

edges = [('A', 'B', 2.0), ('A', 'C', 3.5), ('B', 'C', 1.2)]
adj_matrix = weighted_edges_to_adjacency_matrix(edges)
print(adj_matrix)

出力:

     A    B    C
A  0.0  2.0  3.5
B  2.0  0.0  1.2
C  3.5  1.2  0.0

ご希望であれば、同じノード間に複数エッジがある場合の扱い(加算・最大・平均など)にも対応できます。必要であれば教えてください。

user:

得られた adj_matrix の重みの絶対値の最大値を得る関数を書いてください。

assistant:

以下は、pandas.DataFrame 形式の隣接行列から 重みの絶対値の最大値を取得する関数です。


✅ 関数定義:

def max_abs_weight(adj_matrix):
    """
    隣接行列の中の重みの絶対値の最大値を返す。

    Parameters:
    - adj_matrix: pandas.DataFrame(隣接行列)

    Returns:
    - float: 絶対値の最大重み
    """
    return adj_matrix.abs().to_numpy().max()

使用例:

import pandas as pd

# 例として手動で隣接行列を定義
adj_matrix = pd.DataFrame({
    'A': [0.0, -2.0, 3.5],
    'B': [-2.0, 0.0, 1.2],
    'C': [3.5, 1.2, 0.0]
}, index=['A', 'B', 'C'])

max_weight = max_abs_weight(adj_matrix)
print(max_weight)

出力:

3.5

この関数は、正負問わず最大の重みを見つけたいときに便利です。
他にも「非ゼロ要素の最大値」などの条件があれば、それに応じて調整できます。必要があればお知らせください。

user:

adj_matrix が pandas dataframe ではなく ndarray の場合は?

assistant:

adj_matrixNumPyndarray である場合も、絶対値の最大値を取得する関数は非常にシンプルに書けます。


✅ NumPy 配列(ndarray)版の関数:

import numpy as np

def max_abs_weight_ndarray(adj_matrix):
    """
    NumPy配列の隣接行列における重みの絶対値の最大値を返す。

    Parameters:
    - adj_matrix: numpy.ndarray(隣接行列)

    Returns:
    - float: 絶対値の最大重み
    """
    return np.abs(adj_matrix).max()

使用例:

import numpy as np

# 例として隣接行列を NumPy 配列で作成
adj_matrix = np.array([
    [ 0.0, -2.0,  3.5],
    [-2.0,  0.0,  1.2],
    [ 3.5,  1.2,  0.0]
])

max_weight = max_abs_weight_ndarray(adj_matrix)
print(max_weight)

出力:

3.5

補足:

  • np.abs(adj_matrix):行列のすべての要素の絶対値を取る
  • .max():最大値を取得する

pandas.DataFrame と異なり、ndarray では .abs() ではなく np.abs() を使う点に注意してください。

user:

ndarrayでもpd dataframeでもどっちでも大丈夫な関数にしてください。

assistant:

了解しました!
adj_matrixpandas.DataFrame でも numpy.ndarray でも動作する汎用関数を以下に示します。


✅ 両方対応した関数:

import numpy as np
import pandas as pd

def max_abs_weight_general(adj_matrix):
    """
    隣接行列が pandas.DataFrame または numpy.ndarray のいずれでも、
    重みの絶対値の最大値を返す。

    Parameters:
    - adj_matrix: pandas.DataFrame または numpy.ndarray

    Returns:
    - float: 絶対値の最大重み
    """
    if isinstance(adj_matrix, pd.DataFrame):
        values = adj_matrix.values  # DataFrame → ndarray に変換
    elif isinstance(adj_matrix, np.ndarray):
        values = adj_matrix
    else:
        raise TypeError("adj_matrix must be a pandas.DataFrame or numpy.ndarray")

    return np.abs(values).max()

使用例①(pandas.DataFrame):

df = pd.DataFrame({
    'A': [0.0, -2.0, 3.5],
    'B': [-2.0, 0.0, 1.2],
    'C': [3.5, 1.2, 0.0]
}, index=['A', 'B', 'C'])

print(max_abs_weight_general(df))  # 出力: 3.5

使用例②(numpy.ndarray):

arr = np.array([
    [ 0.0, -2.0,  3.5],
    [-2.0,  0.0,  1.2],
    [ 3.5,  1.2,  0.0]
])

print(max_abs_weight_general(arr))  # 出力: 3.5

この関数を使えば、データの形式を気にせず共通に使えるので便利です。
さらに対応形式(例:torch.Tensorなど)を増やしたい場合も簡単に拡張できます。

user:

ありがとうございます。先ほどの weighted_edges_to_adjacency_matrix 関数ですが、 edges が全ての node を網羅しているとは限らないため、edge で結ばれない node がある場合は、隣接行列のサイズが不当に小さくなることがあります。これを避けるために、オプションとして column 名(node名)のリストを入れると、edgeで結ばれないnodeがある場合も隣接行列に含めるように関数を書き換えてください。

assistant:

以下に、すべてのノード名を外部から指定できるように拡張した weighted_edges_to_adjacency_matrix 関数を提示します。

このバージョンでは、nodes 引数を追加で指定でき、edges に含まれていないノードも隣接行列に必ず含められるようになります。


✅ 改良版:未接続ノードも含める

import pandas as pd

def weighted_edges_to_adjacency_matrix(edges, directed=False, nodes=None):
    """
    重み付きの辺リストから隣接行列(pandas DataFrame)を作成する。
    edges で指定されていないノードも、nodes 引数で明示的に与えることで隣接行列に含めることができる。
    
    Parameters:
    - edges: list of tuple (node1, node2, weight)
    - directed: bool, 有向グラフなら True, 無向グラフなら False
    - nodes: list of node names(任意)。全ノードを明示的に指定する場合に使用。

    Returns:
    - pandas.DataFrame: 隣接行列(値は重み、辺がなければ0)
    """
    # edges に含まれるノードを取得
    edge_nodes = set(n for edge in edges for n in edge[:2])

    # 全ノードリストを決定
    if nodes is not None:
        all_nodes = sorted(set(nodes))  # 重複削除+ソート
    else:
        all_nodes = sorted(edge_nodes)

    # 隣接行列を初期化(すべて0.0)
    adj_matrix = pd.DataFrame(0.0, index=all_nodes, columns=all_nodes)

    # エッジに従って重みを設定
    for src, dst, weight in edges:
        adj_matrix.loc[src, dst] = weight
        if not directed:
            adj_matrix.loc[dst, src] = weight

    return adj_matrix

✅ 使用例

edges = [('A', 'B', 2.0), ('B', 'C', 1.5)]
all_nodes = ['A', 'B', 'C', 'D']  # D はどのエッジにも登場しない

adj_matrix = weighted_edges_to_adjacency_matrix(edges, directed=False, nodes=all_nodes)
print(adj_matrix)

出力:

     A    B    C    D
A  0.0  2.0  0.0  0.0
B  2.0  0.0  1.5  0.0
C  0.0  1.5  0.0  0.0
D  0.0  0.0  0.0  0.0

このようにすれば、nodes に含めたすべてのノードが隣接行列に現れるようになります。
他にも「重みのデフォルト値」や「欠損値は NaN にしたい」などのカスタマイズがあれば追加できますので、お気軽にお知らせください。

user:

ありがとうございます。今日のこれまでの会話をブログに書き残したいので、タイトル案をいくつか提案してください。

assistant:

こちらこそありがとうございます!
本日のやりとりは「グラフデータの取り扱いと可視化のための隣接行列処理」に関する実践的な内容でしたので、以下のようなブログタイトル案はいかがでしょうか?


✅ シンプル・技術寄りなタイトル案

  1. 「Pythonで重み付きグラフの隣接行列を作成する方法」
  2. 「pandasとNumPyで隣接行列を自在に操る」
  3. 「未接続ノードもOK!柔軟な隣接行列生成関数の実装」
  4. 「重み付きエッジリストから隣接行列を生成し、最大重みを取得する」
  5. 「DataFrameとndarray両対応!グラフ構造の最大重みを求める関数」

✅ ブログ・読み物っぽいタイトル案

  1. 「ノードが孤立していても大丈夫:隣接行列を柔軟に作る」
  2. 「pandasとNumPyで始めるグラフ処理の基本レシピ」
  3. 「重み付きエッジと仲良くなる:隣接行列づくりの実践メモ」
  4. 「グラフの重みを最大値で読み解く:Pythonによる隣接行列入門」
  5. 「一歩進んだ隣接行列の扱い方:孤立ノードや型の違いにも対応」

もし記事のターゲット(例:初心者・研究者・データサイエンス実務者など)や使いたいキーワードがあれば、さらに絞り込んだタイトル案もご提案できます。お気軽にお知らせください!

user:

「未接続ノードがあってもOK!重み付きエッジリストから隣接行列を生成する関数の実装」でいきたいと思います。最後に今回のまとめを書いてください。

assistant:

いいタイトルですね!では、そのタイトルにふさわしいブログ記事のまとめを以下にご用意しました:


✅ まとめ:「未接続ノードがあってもOK!重み付きエッジリストから隣接行列を生成する関数の実装」

本記事では、Python を使って 重み付きエッジリストから隣接行列を生成する方法について解説しました。特に以下の点をカバーしています:

  • エッジリスト形式 [(node1, node2, weight), ...]pandas.DataFrame の隣接行列に変換する基本関数の実装
  • 有向グラフ・無向グラフの切り替えに対応する柔軟な設計
  • 未接続のノード(孤立ノード)も隣接行列に含めるための nodes オプションの導入
  • 隣接行列から 重みの絶対値の最大値を取得する汎用関数DataFramendarray 両対応)

これらの機能を備えることで、ネットワーク分析や可視化、機械学習への前処理など、幅広い用途に対応できる堅牢な隣接行列処理関数を作成できます。

今後はこのベースを拡張して、可視化(networkx + pyvis)、クラスタリング、中心性指標の計算などへとつなげていくのも良いでしょう。


必要に応じて、冒頭や本文に貼れる「実装コード一覧」などもまとめられます。
さらに内容を発展させたい場合や、可視化や応用例などの追加もお気軽にご相談ください!

user:

ありがとうございます。今回はこれで大丈夫です。また今後ともよろしくお願いします!

assistant:

どういたしまして!こちらこそ、丁寧にやりとりしてくださってありがとうございました。
またいつでもお気軽にご相談ください。ブログ執筆や実装の続きをサポートできるのを楽しみにしています!

今後ともどうぞよろしくお願いします 😊

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?