Add positional argument to choose correlation methods (Pearson or
Spearman)
This commit is contained in:
+19
-6
@@ -10,9 +10,21 @@ import pandas as pd
|
|||||||
import plotly.graph_objects as go
|
import plotly.graph_objects as go
|
||||||
|
|
||||||
from utils.extractor import load_data
|
from utils.extractor import load_data
|
||||||
from utils.extractor import to_int
|
|
||||||
|
|
||||||
def calculate_correlation(df: pd.DataFrame, target_id: str | None = None) -> pd.DataFrame:
|
|
||||||
|
def _to_int(x):
|
||||||
|
"""Convert a hex string or integer to int, returning NaN on failure."""
|
||||||
|
if isinstance(x, (int, np.integer)):
|
||||||
|
return int(x)
|
||||||
|
if isinstance(x, str):
|
||||||
|
try:
|
||||||
|
return int(x, 16)
|
||||||
|
except ValueError:
|
||||||
|
return np.nan
|
||||||
|
return np.nan
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_correlation(df: pd.DataFrame, method: str, target_id: str | None = None) -> pd.DataFrame:
|
||||||
"""Calculates inter-byte correlation grouped by identifier."""
|
"""Calculates inter-byte correlation grouped by identifier."""
|
||||||
byte_cols = [f"b{i}" for i in range(8)]
|
byte_cols = [f"b{i}" for i in range(8)]
|
||||||
available_cols = [col for col in byte_cols if col in df.columns]
|
available_cols = [col for col in byte_cols if col in df.columns]
|
||||||
@@ -22,16 +34,16 @@ def calculate_correlation(df: pd.DataFrame, target_id: str | None = None) -> pd.
|
|||||||
|
|
||||||
df_bytes = df[["Identifier"] + available_cols].copy()
|
df_bytes = df[["Identifier"] + available_cols].copy()
|
||||||
for col in available_cols:
|
for col in available_cols:
|
||||||
df_bytes[col] = df_bytes[col].apply(to_int)
|
df_bytes[col] = df_bytes[col].apply(_to_int)
|
||||||
|
|
||||||
if target_id:
|
if target_id:
|
||||||
group = df_bytes[df_bytes["Identifier"] == target_id]
|
group = df_bytes[df_bytes["Identifier"] == target_id]
|
||||||
if group.empty:
|
if group.empty:
|
||||||
raise ValueError(f"Identifier '{target_id}' not found in data")
|
raise ValueError(f"Identifier '{target_id}' not found in data")
|
||||||
return group[available_cols].corr().fillna(0.0)
|
return group[available_cols].corr(method=method).fillna(0.0)
|
||||||
|
|
||||||
def max_abs_corr(group: pd.DataFrame) -> pd.Series:
|
def max_abs_corr(group: pd.DataFrame) -> pd.Series:
|
||||||
corr_arr = np.abs(group.corr().to_numpy().copy())
|
corr_arr = np.abs(group.corr(method=method).to_numpy().copy())
|
||||||
np.fill_diagonal(corr_arr, 0.0)
|
np.fill_diagonal(corr_arr, 0.0)
|
||||||
return pd.Series(corr_arr.max(axis=0), index=group.columns).fillna(0.0)
|
return pd.Series(corr_arr.max(axis=0), index=group.columns).fillna(0.0)
|
||||||
|
|
||||||
@@ -109,6 +121,7 @@ def plot_correlation_heatmap(corr_df: pd.DataFrame, target_id: str | None, title
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description="Analyze CAN bus inter-byte correlation")
|
parser = argparse.ArgumentParser(description="Analyze CAN bus inter-byte correlation")
|
||||||
|
parser.add_argument("method", choices=["pearson", "spearman"], help="Correlation method to use")
|
||||||
parser.add_argument("input", type=Path, help="Path to the input CAN log file")
|
parser.add_argument("input", type=Path, help="Path to the input CAN log file")
|
||||||
parser.add_argument("output", type=Path, nargs="?", default=Path("correlation_report.html"), help="Path to the output HTML report")
|
parser.add_argument("output", type=Path, nargs="?", default=Path("correlation_report.html"), help="Path to the output HTML report")
|
||||||
parser.add_argument("title", nargs="?", default="CAN Bus Inter-Byte Correlation", help="Title for the HTML report")
|
parser.add_argument("title", nargs="?", default="CAN Bus Inter-Byte Correlation", help="Title for the HTML report")
|
||||||
@@ -116,7 +129,7 @@ if __name__ == "__main__":
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
df = load_data(args.input)
|
df = load_data(args.input)
|
||||||
corr_df = calculate_correlation(df, target_id=args.identifier)
|
corr_df = calculate_correlation(df, method=args.method, target_id=args.identifier)
|
||||||
|
|
||||||
display_title = f"{args.title} ({args.identifier})" if args.identifier else args.title
|
display_title = f"{args.title} ({args.identifier})" if args.identifier else args.title
|
||||||
fig = plot_correlation_heatmap(corr_df, target_id=args.identifier, title=display_title)
|
fig = plot_correlation_heatmap(corr_df, target_id=args.identifier, title=display_title)
|
||||||
|
|||||||
Reference in New Issue
Block a user