モル濃度に基づく NaOH 溶液の pH

化学濃度を扱う際、pH スケールの対数的な性質がデータの可視化を難しくすることがよくあります。標準の線形スケールでモル濃度に対する pH をプロットすると、イオンの比例関係を隠してしまう「ホッケースティック」曲線になります。

この投稿では、Python と matplotlib を使って、0 から高濃度の 3 モルまでの水酸化ナトリウム(NaOH)の pH を可視化し、線形スケールと対数スケールを比較してどちらがより良い洞察を与えるかを確認します。

pH NaOH molarity.svg

化学のロジック

NaOH は強塩基なので完全に解離します。広い範囲、特に 1.0M を超えた範囲で pH を正確に計算するために、まず pOH を計算します:

$$pOH = -\log_{10}[OH^-]$$

$$pH = 14 - pOH$$

興味深いことに、3M NaOH では pOH が負($\approx -0.48$)になり、pH は実際に 14.48 まで上昇して、教科書の一般的な「0 から 14」ルールを超えます。

Python 実装

濃度範囲の生成に numpy、クリーンでプロフェッショナルな外観のために ggplot スタイルを使った matplotlib.pyplot を使用します。異なる視点を強調するために 2 つの個別のプロットを生成することに注意してください。

ph_naoh_molarity.py
#!/usr/bin/env python3
# SPDX-License-Identifier: CC0-1.0
import numpy as np
import matplotlib.pyplot as plt

# スタイルを ggplot に設定
plt.style.use('ggplot')

def calculate_ph(molarity):
    """水の自己イオン化を含む、与えられた NaOH モル濃度の pH を計算する。"""
    kw = 1e-14
    # 低濃度を正確に扱うための [OH-] の 2 次方程式解法
    oh_conc = (molarity + np.sqrt(molarity**2 + 4 * kw)) / 2
    poh = -np.log10(oh_conc)
    return 14 - poh

# 線形プロット用データ(0 〜 3M)
x_linear = np.linspace(0, 3, 1000)
y_linear = calculate_ph(x_linear)

# 対数プロット用データ(0.01 〜 3M)
# logspace を使うと対数スケールで滑らかにプロットできる
x_log = np.logspace(np.log10(0.01), np.log10(3), 1000)
y_log = calculate_ph(x_log)

# 線形スケールプロットの作成
plt.figure(figsize=(10, 6))
plt.plot(x_linear, y_linear, color='#E24A33', linewidth=2.5, label='pH Value')
plt.title('pH of NaOH Solution (Linear Scale: 0M to 3M)', fontsize=14, fontweight='bold')
plt.xlabel('Molarity of NaOH (mol/L)', fontsize=12)
plt.ylabel('pH', fontsize=12)
plt.ylim(7, 15)
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
plt.savefig('ph_linear_scale.png', dpi=300)
plt.close()

# 対数スケールプロットの作成
plt.figure(figsize=(10, 6))
plt.plot(x_log, y_log, color='#348ABD', linewidth=2.5, label='pH Value')
plt.xscale('log')
plt.title('pH of NaOH Solution (Log Scale: 0.01M to 3M)', fontsize=14, fontweight='bold')
plt.xlabel('Molarity of NaOH (Logarithmic Scale mol/L)', fontsize=12)
plt.ylabel('pH', fontsize=12)
plt.ylim(11.5, 15) # 0.01M-3M ウィンドウに焦点を絞った範囲
plt.grid(True, which="both", linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
plt.savefig('ph_log_scale.png', dpi=300)
plt.close()

# タグに単一の「メイン」ファイル名を提供するシステム要件のため、
# 結合バージョンも保存する。
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 12))

# 線形プロット
ax1.plot(x_linear, y_linear, color='#E24A33', linewidth=2.5)
ax1.set_title('Linear Scale (0M to 3M)', fontsize=14, fontweight='bold')
ax1.set_ylabel('pH')
ax1.set_ylim(7, 15)

# 対数プロット
ax2.plot(x_log, y_log, color='#348ABD', linewidth=2.5)
ax2.set_xscale('log')
ax2.set_title('Logarithmic Scale (0.01M to 3M)', fontsize=14, fontweight='bold')
ax2.set_xlabel('Molarity of NaOH (mol/L)')
ax2.set_ylabel('pH')
ax2.set_ylim(11.5, 15)

plt.tight_layout()
plt.savefig('pH NaOH molarity.svg', dpi=300)

同じカテゴリの類似記事をチェック: 化学