| |
|
| |
|
| | import networkx as nx
|
| | import pandas as pd
|
| | import logging
|
| |
|
| |
|
| | try:
|
| | import community.community_louvain as community_louvain
|
| | community_lib_available = True
|
| | except ImportError:
|
| | logging.warning("'community' (python-louvain) kütüphanesi bulunamadı. Topluluk tespiti yapılamayacak. Kurulum için: pip install python-louvain community")
|
| | community_lib_available = False
|
| |
|
| |
|
| | from src.data_management import storage
|
| |
|
| | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| |
|
| | def calculate_centrality(graph: nx.Graph) -> dict:
|
| | """
|
| | Graf üzerindeki düğümler için merkeziyet metriklerini hesaplar.
|
| |
|
| | Args:
|
| | graph (nx.Graph): Analiz edilecek NetworkX grafı.
|
| |
|
| | Returns:
|
| | dict: {node_id: {'degree': float, 'betweenness': float, 'eigenvector': float (veya None)}}
|
| | formatında metrikleri içeren sözlük.
|
| | """
|
| | metrics = {}
|
| | if not graph or graph.number_of_nodes() == 0:
|
| | return metrics
|
| |
|
| | try:
|
| | degree_centrality = nx.degree_centrality(graph)
|
| | except Exception as e:
|
| | logging.error(f"Degree Centrality hesaplanırken hata: {e}")
|
| | degree_centrality = {}
|
| |
|
| | try:
|
| | betweenness_centrality = nx.betweenness_centrality(graph)
|
| | except Exception as e:
|
| | logging.error(f"Betweenness Centrality hesaplanırken hata: {e}")
|
| | betweenness_centrality = {}
|
| |
|
| | try:
|
| |
|
| |
|
| | eigenvector_centrality = nx.eigenvector_centrality(graph, max_iter=500, tol=1e-06)
|
| | except Exception as e:
|
| | logging.warning(f"Eigenvector Centrality hesaplanırken hata (graf bağlantısız olabilir): {e}")
|
| | eigenvector_centrality = {}
|
| |
|
| |
|
| | for node in graph.nodes():
|
| | metrics[node] = {
|
| | 'degree_centrality': degree_centrality.get(node, 0.0),
|
| | 'betweenness_centrality': betweenness_centrality.get(node, 0.0),
|
| | 'eigenvector_centrality': eigenvector_centrality.get(node, None)
|
| | }
|
| | logging.info("Merkeziyet metrikleri hesaplandı.")
|
| | return metrics
|
| |
|
| | def detect_communities(graph: nx.Graph) -> dict | None:
|
| | """
|
| | Louvain algoritması kullanarak graf üzerindeki toplulukları tespit eder.
|
| |
|
| | Args:
|
| | graph (nx.Graph): Analiz edilecek NetworkX grafı.
|
| |
|
| | Returns:
|
| | dict | None: {node_id: community_id} formatında bölümleme sözlüğü veya hata/kütüphane yoksa None.
|
| | """
|
| | if not community_lib_available:
|
| | return None
|
| | if not graph or graph.number_of_nodes() == 0:
|
| | return None
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | try:
|
| | partition = community_louvain.best_partition(graph, weight='weight')
|
| | num_communities = len(set(partition.values()))
|
| | logging.info(f"Louvain ile topluluk tespiti tamamlandı. {num_communities} topluluk bulundu.")
|
| | return partition
|
| | except Exception as e:
|
| | logging.exception(f"Topluluk tespiti sırasında hata oluştu: {e}")
|
| | return None
|
| |
|
| |
|
| | def get_network_analysis_results(graph: nx.Graph) -> pd.DataFrame | None:
|
| | """
|
| | Merkeziyet ve topluluk analizlerini yapar ve sonuçları bir DataFrame'de birleştirir.
|
| |
|
| | Args:
|
| | graph (nx.Graph): Analiz edilecek NetworkX grafı.
|
| |
|
| | Returns:
|
| | pd.DataFrame | None: 'concept_id', 'name', 'degree_centrality', 'betweenness_centrality',
|
| | 'eigenvector_centrality', 'community_id' sütunlarını içeren DataFrame
|
| | veya hata durumunda None.
|
| | """
|
| | if not graph or graph.number_of_nodes() == 0:
|
| | logging.warning("Analiz için boş veya geçersiz graf sağlandı.")
|
| | return None
|
| |
|
| | logging.info("Ağ analizi metrikleri hesaplanıyor...")
|
| | centrality_metrics = calculate_centrality(graph)
|
| | community_partition = detect_communities(graph)
|
| |
|
| |
|
| | analysis_data = []
|
| | concepts_df = storage.load_dataframe('concepts', storage.CONCEPT_COLUMNS)
|
| |
|
| | for node_id, metrics in centrality_metrics.items():
|
| | node_data = {
|
| | 'concept_id': node_id,
|
| | 'name': graph.nodes[node_id].get('name', 'N/A'),
|
| | 'degree_centrality': metrics.get('degree_centrality'),
|
| | 'betweenness_centrality': metrics.get('betweenness_centrality'),
|
| | 'eigenvector_centrality': metrics.get('eigenvector_centrality'),
|
| | 'community_id': community_partition.get(node_id, -1) if community_partition else -1
|
| | }
|
| | analysis_data.append(node_data)
|
| |
|
| | if not analysis_data:
|
| | logging.warning("Ağ analizi sonucu veri üretilemedi.")
|
| | return None
|
| |
|
| | analysis_df = pd.DataFrame(analysis_data)
|
| |
|
| |
|
| | if 'N/A' in analysis_df['name'].values and concepts_df is not None:
|
| | analysis_df = analysis_df.drop(columns=['name'])
|
| | analysis_df = pd.merge(analysis_df, concepts_df[['concept_id', 'name']], on='concept_id', how='left')
|
| |
|
| | cols = ['concept_id', 'name'] + [col for col in analysis_df.columns if col not in ['concept_id', 'name']]
|
| | analysis_df = analysis_df[cols]
|
| |
|
| |
|
| | logging.info("Ağ analizi sonuçları DataFrame'e dönüştürüldü.")
|
| | return analysis_df
|
| |
|
| |
|
| | def save_network_analysis(analysis_df: pd.DataFrame):
|
| | """ Ağ analizi sonuçlarını Parquet dosyasına kaydeder. """
|
| | if analysis_df is not None and not analysis_df.empty:
|
| | storage.save_dataframe(analysis_df, storage.NETWORK_ANALYSIS_FILENAME)
|
| | logging.info(f"Ağ analizi sonuçları '{storage.NETWORK_ANALYSIS_FILENAME}.parquet' olarak kaydedildi.")
|
| | else:
|
| | logging.warning("Kaydedilecek ağ analizi sonucu bulunamadı.") |