箱ひげ図の作成

注: これは、Charts with Widgets Galleryの例の一部です。

この例題では、ファイルから非連続データを読み込んで整理し、箱ひげ図に必要な中央値を求める方法も示しています。

2つの会社のシェア偏差を表示するために、まず月次データを扱う2つのQBoxPlotSeries

auto acmeSeries = new QBoxPlotSeries;
acmeSeries->setName("Acme Ltd");

auto boxWhiskSeries = new QBoxPlotSeries;
boxWhiskSeries->setName("BoxWhisk Inc");

QFile BoxDataReaderクラスは、非連続データが保存されているテキスト・ファイルをオープンするために使用されます。BoxDataReader は、テキスト・ファイルを読み込んで、データから極値と中央値を求めるための補助クラスです。BoxDataReader については後で詳しく説明します。メソッド readBox は値を読み取り、メソッドが呼び出し元に返す アイテムに設定します。返された アイテムがシリーズに追加されます。QBoxSet QBoxSet

QFile acmeData(":boxplot_a");
const QString errorTemplate = QStringLiteral("Failed to load '%1' file.");
if (!acmeData.open(QIODevice::ReadOnly | QIODevice::Text)) {
    m_loadError = errorTemplate.arg(acmeData.fileName());
    return false;
}

BoxPlotDataReader dataReader(&acmeData);
while (!dataReader.atEnd()) {
    QBoxSet *set = dataReader.readBox();
    if (set)
        acmeSeries->append(set);
}

このセクションでは、2つ目の会社のデータを読み込むために2つ目のファイルがオープンされます。

QFile boxwhiskData(":boxplot_b");
if (!boxwhiskData.open(QIODevice::ReadOnly | QIODevice::Text)) {
    m_loadError = errorTemplate.arg(acmeData.fileName());
    return false;
}

dataReader.readFile(&boxwhiskData);
while (!dataReader.atEnd()) {
    QBoxSet *set = dataReader.readBox();
    if (set)
        boxWhiskSeries->append(set);
}

このコード・スニペットでは、新しいQChart インスタンスが作成され、以前に作成されたシリーズがそれに追加されます。タイトルも定義され、アニメーションはSeriesAnimationに設定されています。

auto chart = new QChart;
chart->addSeries(acmeSeries);
chart->addSeries(boxWhiskSeries);
chart->setTitle("Acme Ltd. and BoxWhisk Inc. share deviation in 2012");
chart->setAnimationOptions(QChart::SeriesAnimations);

ここでは、プレゼンテーション用のデフォルトの軸を作成するようにチャートに依頼しています。また、チャートから軸のポインタをクエリして、その軸の最小値と最大値を設定することにより、垂直軸の範囲を設定します。

chart->createDefaultAxes();
chart->axes(Qt::Vertical).first()->setMin(15.0);
chart->axes(Qt::Horizontal).first()->setMax(34.0);

このセクションでは、凡例を表示するように設定し、それをチャートの下部に配置します。

chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignBottom);

最後に、チャートをビューに追加します。また、chartViewのアンチエイリアスをオンにします。

createDefaultChartView(chart);

これでチャートを表示する準備が整いました。

ここでは readBox メソッドについて詳しく説明する。

まず、ファイルから1行が読み込まれ、#で始まる行はコメント行とみなされるため拒否される。

QString line = m_textStream.readLine();
if (line.startsWith("#"))
    return nullptr;

このファイルでは、データは数字、空白、数字、空白の順に並んでいる。このスニペットでは、行は1つの数字列に分割され、QStringList に格納される。

QStringList strList = line.split(QLatin1Char(' '), Qt::SkipEmptyParts);

sortedListは数字を連続した順序で保持する。まずsortedListがクリアされ、strListから数字が読み込まれ、sortedListにdouble形式で格納される。qSortメソッドはsortedListを小さいものから順番に並べていく。

m_sortedList.clear();
for (int i = 1; i < strList.count(); i++)
    m_sortedList.append(strList.at(i).toDouble());

std::sort(m_sortedList.begin(), m_sortedList.end());

以下は、連続データから極値と中央値を選択する方法を示すコードサンプルである。まず、新しいQBoxSet が作成される。下限と上限の選択方法は簡単で、sortedList の最初と最後の項目を選択するだけです。中央値については、後で説明するヘルパー・メソッド findMedian を使います。上半分の中央値については、数値の量が偶数か不均等か、開始数値を調整する必要がある。下半分の終了数は、intの丸めから自然に得られます。

auto box = new QBoxSet(strList.first());
box->setValue(QBoxSet::LowerExtreme, m_sortedList.first());
box->setValue(QBoxSet::UpperExtreme, m_sortedList.last());
box->setValue(QBoxSet::Median, findMedian(0, count));
box->setValue(QBoxSet::LowerQuartile, findMedian(0, count / 2));
box->setValue(QBoxSet::UpperQuartile, findMedian(count / 2 + (count % 2), count));

以下にfindMedianメソッドのコードサンプルを示します。数値の量が不均等な場合は、真ん中の数値を選択します。偶数の場合は真ん中から2つ取って平均値を計算します。

int count = end - begin;
if (count % 2) {
    return m_sortedList.at(count / 2 + begin);
} else {
    qreal right = m_sortedList.at(count / 2 + begin);
    qreal left = m_sortedList.at(count / 2 - 1 + begin);
    return (right + left) / 2.0;
}

本書に含まれる文書の著作権は、それぞれの所有者に帰属します 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。