箱ひげ図の作成
注: これは、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つ取って平均値を計算します。
本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。