# =====================================
# Attack × Speed Tradeoff Analysis (Full Version)
# =====================================
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize_scalar
# --- Dataset ---
data = {
"Generation": ["I", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
"Pokemon": ["Dragonite", "Salamence", "Garchomp", "Hydreigon",
"Goodra", "Kommo-o", "Dragapult", "Baxcalibur"],
"Attack": [134, 135, 130, 105, 100, 110, 120, 145],
"Speed": [80, 100, 102, 98, 80, 85, 142, 87]
}
df = pd.DataFrame(data)
# --- 1. Attack×Speed 計算 ---
df["Atk×Spd"] = df["Attack"] * df["Speed"]
mean_value = df["Atk×Spd"].mean()
a = mean_value # 反比例線 y = a/x のパラメータ
# =====================================
# 2. Attack×Speed 棒グラフ
# =====================================
plt.figure(figsize=(9, 5))
bars = plt.bar(df["Pokemon"], df["Atk×Spd"], color="royalblue", edgecolor="black")
plt.axhline(mean_value, color="red", linestyle="--", linewidth=1.5,
label=f"Average = {mean_value:.1f}")
for bar in bars:
yval = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2, yval + 1000, f"{int(yval)}",
ha="center", va="bottom", fontsize=9)
plt.title("Attack × Speed of Pseudo Legendary Dragons", fontsize=13)
plt.xlabel("Pokémon")
plt.ylabel("Attack × Speed Value")
plt.legend()
plt.tight_layout()
plt.show()
# =====================================
# 3. Attack–Speed 反比例関係の描画
# =====================================
plt.figure(figsize=(8, 5))
plt.scatter(df["Speed"], df["Attack"], color="royalblue", label="Pokémon Data")
x = np.linspace(min(df["Speed"]) - 10, max(df["Speed"]) + 10, 200)
y = mean_value / x
plt.plot(x, y, color="red", linestyle="--", label="y = mean_value/x")
for i, txt in enumerate(df["Pokemon"]):
plt.text(df["Speed"][i] + 1, df["Attack"][i] + 0.5, txt, fontsize=8)
plt.title("Attack–Speed Tradeoff (Inverse Relation)", fontsize=13)
plt.xlabel("Speed")
plt.ylabel("Attack")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# =====================================
# 4. 縦距離(近似的距離)解析
# =====================================
df["Attack_ideal"] = mean_value / df["Speed"]
df["Vertical_Diff"] = df["Attack"] - df["Attack_ideal"]
df["Distance_to_Curve"] = abs(df["Vertical_Diff"])
plt.figure(figsize=(8, 5))
plt.scatter(df["Speed"], df["Attack"], color="royalblue", label="Pokémon")
plt.plot(x, y, color="red", linestyle="--", label="y = mean_value/x")
# 垂線描画(近似)
for i in range(len(df)):
plt.plot([df["Speed"][i], df["Speed"][i]],
[df["Attack"][i], df["Attack_ideal"][i]],
color="gray", linestyle=":", linewidth=1)
for i, txt in enumerate(df["Pokemon"]):
plt.text(df["Speed"][i] + 1, df["Attack"][i] + 0.5, txt, fontsize=8)
plt.title("Vertical Distance from Tradeoff Curve", fontsize=13)
plt.xlabel("Speed")
plt.ylabel("Attack")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
print("=== Vertical Distance Table ===")
print(df[["Pokemon", "Speed", "Attack", "Attack_ideal", "Vertical_Diff", "Distance_to_Curve"]].round(2))
# =====================================
# 5. 最短距離(厳密計算)
# =====================================
def distance_to_curve(x, x0, y0, a):
y = a / x
return np.sqrt((x - x0)**2 + (y - y0)**2)
shortest_dist = []
x_foot = []
y_foot = []
for i in range(len(df)):
x0, y0 = df["Speed"][i], df["Attack"][i]
res = minimize_scalar(distance_to_curve, bounds=(1, 300),
args=(x0, y0, a), method="bounded")
x1 = res.x
y1 = a / x1
dmin = distance_to_curve(x1, x0, y0, a)
shortest_dist.append(dmin)
x_foot.append(x1)
y_foot.append(y1)
df["x_foot"] = x_foot
df["y_foot"] = y_foot
df["Shortest_Dist"] = shortest_dist
# --- 最短距離プロット ---
plt.figure(figsize=(9, 6))
x = np.linspace(50, 160, 400)
y = a / x
plt.plot(x, y, "r--", label="Inverse Tradeoff: y = a/x")
plt.scatter(df["Speed"], df["Attack"], color="royalblue", label="Pokémon")
plt.scatter(df["x_foot"], df["y_foot"], color="orange", s=30, label="Foot of Perpendicular")
# 垂線を描画(最短距離)
for i in range(len(df)):
plt.plot([df["Speed"][i], df["x_foot"][i]],
[df["Attack"][i], df["y_foot"][i]], color="gray", linestyle=":")
for i, txt in enumerate(df["Pokemon"]):
plt.text(df["Speed"][i] + 1, df["Attack"][i] + 1, txt, fontsize=8)
plt.title("Shortest Distance from Inverse Tradeoff Curve", fontsize=13)
plt.xlabel("Speed")
plt.ylabel("Attack")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
print("=== Shortest Distance to Tradeoff Curve ===")
print(df[["Pokemon", "Speed", "Attack", "Shortest_Dist"]].round(3))