import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 更新后的數(shù)據(jù)點(diǎn)
points = {
'blue': np.array([
[-12, 6, 0],
[-13, 3, 0],
[-15, 1, 0]
]),
'green': np.array([
[2, 0, 0],
[3, 0, 0],
[4, -2, 0]
]),
'orange': np.array([
[-2, 8, 8],
[-4, 3, 2]
]),
'pink': np.array([
[-3, 6, 5],
[-5, 2, 3],
])
}
def draw_ellipsoid(ax, center, radii, rotation, color, alpha=0.2):
u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)
x = radii[0] * np.outer(np.cos(u), np.sin(v))
y = radii[1] * np.outer(np.sin(u), np.sin(v))
z = radii[2] * np.outer(np.ones_like(u), np.cos(v))
for i in range(len(x)):
for j in range(len(x)):
[x[i,j],y[i,j],z[i,j]] = np.dot([x[i,j],y[i,j],z[i,j]], rotation) + center
ax.plot_surface(x, y, z, color=color, alpha=alpha)
# 創(chuàng)建圖形
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 設(shè)置白色背景
ax.xaxis.pane.fill = False
ax.yaxis.pane.fill = False
ax.zaxis.pane.fill = False
ax.xaxis.pane.set_edgecolor('white')
ax.yaxis.pane.set_edgecolor('white')
ax.zaxis.pane.set_edgecolor('white')
ax.set_facecolor('white')
# 繪制散點(diǎn)圖和橢圓
for color, coords in points.items():
# 繪制散點(diǎn)
ax.scatter(coords[:, 0], coords[:, 1], coords[:, 2],
c=color, s=100, alpha=1.0)
# 添加橢圓
center = np.mean(coords, axis=0)
if color == 'blue':
radii = [2, 3, 1]
rotation = np.array([[0.8, -0.2, 0], [0.2, 0.8, 0], [0, 0, 1]])
elif color == 'green':
radii = [2, 2, 1]
rotation = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
elif color in ['orange', 'pink']:
# 為橙色和粉色點(diǎn)共用一個(gè)更大的橢圓
if color == 'orange':
radii = [3, 4, 4]
rotation = np.array([[0.9, -0.1, 0], [0.1, 0.9, 0], [0, 0, 1]])
draw_ellipsoid(ax, center, radii, rotation, color, alpha=0.1)
# 設(shè)置坐標(biāo)軸標(biāo)簽
ax.set_xlabel('PC1')
ax.set_ylabel('PC2')
ax.set_zlabel('PC3')
# 設(shè)置坐標(biāo)軸范圍
ax.set_xlim([-15, 5])
ax.set_ylim([-5, 10])
ax.set_zlim([-5, 10])
# 設(shè)置網(wǎng)格線
ax.grid(True, linestyle='--', alpha=0.3)
# 調(diào)整視角
ax.view_init(elev=20, azim=-45)
plt.show()
import plotly.graph_objects as go
import plotly.express as px
import numpy as np
from sklearn.manifold import TSNE
def generate_ellipsoid_mesh(center, radii, rotation, n_points=50):
u = np.linspace(0, 2 * np.pi, n_points)
v = np.linspace(0, np.pi, n_points)
x = radii[0] * np.outer(np.cos(u), np.sin(v))
y = radii[1] * np.outer(np.sin(u), np.sin(v))
z = radii[2] * np.outer(np.ones_like(u), np.cos(v))
# 應(yīng)用旋轉(zhuǎn)和平移
points = np.stack([x.flatten(), y.flatten(), z.flatten()])
transformed_points = np.dot(rotation, points) + center.reshape(-1, 1)
x = transformed_points[0].reshape(n_points, n_points)
y = transformed_points[1].reshape(n_points, n_points)
z = transformed_points[2].reshape(n_points, n_points)
return x, y, z
# 年齡分組函數(shù)
def age_to_group(age):
if age == 0:
return 0
elif 0 < age <= 1:
return 1
else:
return int((age-1) // 10 + 2)
# 模擬一些年齡數(shù)據(jù) (如果你沒(méi)有真實(shí)數(shù)據(jù)的話)
np.random.seed(42)
age_values = np.random.uniform(0, 100, size=1000)
# 模擬一些高維數(shù)據(jù) (如果你沒(méi)有真實(shí)的final_V的話)
final_V = np.random.randn(100, 1000) # 100維特征劳闹,1000個(gè)樣本
# 將年齡轉(zhuǎn)換為分組
age_groups = np.array([age_to_group(age) for age in age_values])
# 創(chuàng)建分組標(biāo)簽
group_labels = ['0', '0-1'] + [f'{i*10-9}-{i*10}' for i in range(1, 11)]
# 計(jì)算t-SNE
tsne = TSNE(n_components=3, random_state=42)
features_3d = tsne.fit_transform(final_V.T)
# 創(chuàng)建圖形
fig = go.Figure()
# 使用plotly的顏色序列
colors = px.colors.qualitative.Set3
# 為每個(gè)年齡組添加散點(diǎn)和橢圓
for i, label in enumerate(group_labels):
mask = age_groups == i
if np.sum(mask) > 0: # 如果該組有數(shù)據(jù)點(diǎn)
group_points = features_3d[mask]
# 添加散點(diǎn)
fig.add_trace(go.Scatter3d(
x=group_points[:, 0],
y=group_points[:, 1],
z=group_points[:, 2],
mode='markers',
name=label,
marker=dict(
size=5,
color=colors[i % len(colors)],
opacity=0.6
),
showlegend=True
))
# 計(jì)算并添加橢圓
if len(group_points) > 1:
center = np.mean(group_points, axis=0)
cov = np.cov(group_points.T)
eigenvals, eigenvecs = np.linalg.eigh(cov)
radii = 2 * np.sqrt(eigenvals)
radii = np.maximum(radii, 0.1)
x, y, z = generate_ellipsoid_mesh(center, radii, eigenvecs)
fig.add_trace(go.Surface(
x=x, y=y, z=z,
colorscale=[[0, colors[i % len(colors)]], [1, colors[i % len(colors)]]],
showscale=False,
opacity=0.2,
name=f'{label}_surface',
showlegend=False
))
# 更新布局
fig.update_layout(
title='t-SNE 3D Visualization with Age Groups',
scene=dict(
xaxis_title='t-SNE 1',
yaxis_title='t-SNE 2',
zaxis_title='t-SNE 3',
bgcolor='white'
),
showlegend=True,
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=1.05
),
margin=dict(l=0, r=0, t=30, b=0)
)
# 更新場(chǎng)景配置
fig.update_scenes(
camera=dict(
up=dict(x=0, y=0, z=1),
center=dict(x=0, y=0, z=0),
eye=dict(x=1.5, y=1.5, z=1.5)
)
)
# 顯示圖形
fig.show()