複数の条件に基づいてマーカーの形状を変更する方法

# 複数の条件に基づいてマーカーの形状を変更する方法

データのプロットで複数の条件に応じて異なるマーカー形状を適用することは、視覚的にデータの違いを際立たせる有効な方法です。以下に、PythonのMatplotlibを使用して条件に基づいてマーカーの形状を変更する方法を解説します。

---

## 目次

1. 条件に基づいてデータを分割してプロットする方法
2. リスト内包表記を使用する方法
3. カスタム関数を使用する方法
4. `PathCollection`を直接操作する方法（高度な方法）

---

## 1. 条件に基づいてデータを分割してプロットする方法

条件ごとにデータを分割し、それぞれに異なる`scatter`呼び出しを行うことで、異なるマーカー形状を指定できます。これはシンプルでわかりやすい方法です。

```python
import matplotlib.pyplot as plt
import numpy as np

# データの作成
x = np.random.rand(100)
y = np.random.rand(100)
z = np.random.rand(100)

# 条件設定
condition1 = (z <= 0.3)
condition2 = (z > 0.3) & (z <= 0.7)
condition3 = (z > 0.7)

# 条件ごとにマーカーを指定してプロット
plt.scatter(x[condition1], y[condition1], marker='o', label='z <= 0.3')
plt.scatter(x[condition2], y[condition2], marker='s', label='0.3 < z <= 0.7')
plt.scatter(x[condition3], y[condition3], marker='^', label='z > 0.7')

plt.legend()
plt.show()
```

**ポイント**:
- 各条件ごとに別々にプロットを呼び出すため、コードが分かりやすいです。
- 比較的シンプルな条件分岐に適しています【1】【2】。

---

## 2. リスト内包表記を使用する方法

リスト内包表記を使って条件に基づいたマーカーのリストを作成し、それを基にプロットを行う方法です。この方法はデータの量が少ない場合に便利です。

```python
# 条件に基づいたマーカーリストの作成
markers = ['o' if zi <= 0.3 else 's' if zi <= 0.7 else '^' for zi in z]

# 各マーカータイプごとにプロット
for marker in set(markers):
    mask = np.array(markers) == marker
    plt.scatter(x[mask], y[mask], marker=marker, label=f'Marker {marker}')

plt.legend()
plt.show()
```

**ポイント**:
- リスト内包表記で条件を一度に設定できるため、コードが短くなります。
- 複雑な条件には向きませんが、少数の単純な条件に適しています【3】。

---

## 3. カスタム関数を使用する方法

条件が複雑な場合や、追加のロジックが必要な場合には、カスタム関数を定義してマーカーを決定する方法が役立ちます。

```python
# カスタム関数を定義してマーカーを決定
def get_marker(z_value):
    if z_value <= 0.3:
        return 'o'
    elif z_value <= 0.7:
        return 's'
    else:
        return '^'

# 各データポイントに対してカスタム関数を適用してマーカーを取得
markers = [get_marker(zi) for zi in z]

# 各マーカータイプごとにプロット
for marker in set(markers):
    mask = np.array(markers) == marker
    plt.scatter(x[mask], y[mask], marker=marker, label=f'Marker {marker}')

plt.legend()
plt.show()
```

**ポイント**:
- カスタム関数により、複雑な条件分岐を簡潔に処理できます。
- 複数の条件や変数に基づく柔軟なロジックが必要な場合に最適です【4】。

---

## 4. `PathCollection`を直接操作する方法（高度な方法）

`scatter`オブジェクトの`set_paths`メソッドを使用して、各データポイントのマーカー形状を直接設定する方法です。高度な操作が可能ですが、コードが複雑になるため、より高度なカスタマイズが必要な場合にのみ推奨されます。

```python
import matplotlib.path as mpath

# 基本的な散布図プロット
scatter = plt.scatter(x, y, c=z, cmap='viridis')

# マーカー形状を設定するための辞書とパスリスト
marker_map = {0: 'o', 1: 's', 2: '^'}
paths = [mpath.Path.unit_regular_polygon(i + 3) for i in range(3)]

# 各データポイントに対してマーカーのパスを設定
scatter.set_paths([paths[int(2 * zi)] for zi in z])

plt.colorbar(scatter)
plt.show()
```

**ポイント**:
- `set_paths`メソッドを使用して各点のマーカーをカスタマイズできるため、高度な設定が可能です。
- 条件が非常に多岐にわたる場合や、異なる形状を直接指定したい場合に役立ちます【5】。

---

## まとめ

複数の条件に基づいてマーカーの形状を変更する方法について紹介しました。以下の方法を使用することで、データの特徴をより視覚的にわかりやすく示すことが可能です。

- **条件に基づいてデータを分割してプロット**: シンプルな条件に適した方法。
- **リスト内包表記**: 小規模で単純な条件のデータに適しています。
- **カスタム関数**: 複雑な条件に柔軟に対応可能。
- **`PathCollection`を直接操作**: より高度なカスタマイズが必要な場合に最適。

それぞれの方法には特長があるため、データの特性や条件の複雑さに応じて適切な方法を選択しましょう。

---

## 参考文献

1. Matplotlib Documentation, *Scatter Plot in Matplotlib*. Retrieved from [Matplotlib Docs](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html)
2. How2Matplotlib, *Matplotlib Scatter Marker Size and Shape*. Retrieved from [How2Matplotlib](https://how2matplotlib.com/matplotlib-scatter-marker-size.html)
3. Python Graph Gallery, *Custom Scatter Plot in Matplotlib*. Retrieved from [Python Graph Gallery](https://python-graph-gallery.com/131-custom-a-matplotlib-scatterplot/)
4. E2E Machine Learning, *Matplotlib Points and Markers*. Retrieved from [E2E Machine Learning](https://e2eml.school/matplotlib_points.html)
5. Stack Overflow, *Using Different Markers in a Scatter Plot*. Retrieved from [Stack Overflow](https://stackoverflow.com/questions/75676193/using-different-markers-in-a-scatter-plot)

条件に基づいたマーカー設定を使用して、データの可視化における表現力を高めていきましょう。