用值和日期制作折线图
Make line chart with values and dates
在我的应用程序中,我使用 ios-图表库(swift 替代 MPAndroidChart)。
我只需要显示带有日期和值的折线图。
现在我用这个功能来显示图表
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let lineChartDataSet = LineChartDataSet(yVals: dataEntries, label: "Items count")
let lineChartData = LineChartData(xVals: dataPoints, dataSet: lineChartDataSet)
dateChartView.data = lineChartData
}
这是我的数据:
xItems = ["27.05", "03.06", "17.07", "19.09", "20.09"] //String
let unitsSold = [25.0, 30.0, 45.0, 60.0, 20.0] //Double
但如您所见 - xItems 是 "dd.mm" 格式的日期。因为它们是字符串,所以它们彼此之间有相同的填充。我希望他们在真实日期上更准确。例如 19.09 和 20.09 应该非常接近。我知道我应该每天匹配一些数字才能完成它。但我不知道下一步该怎么做 - 如何调整 x 标签边距?
更新
经过小型研究后,我发现许多开发人员都询问过此功能但没有任何反应 - 就我而言,我在 Swift - PNChart 中找到了这个库的非常有趣的替代方案。简单易用,解决了我的问题。
最简单的解决方案是遍历您的数据并添加值为 0 的 ChartDataEntry
和每个缺失日期的相应标签。
为了回答评论中的问题,这里是我的一个应用程序的屏幕截图,我在其中用 0 值填充日期空白:
在我的例子中,我想要 0 值而不是从数据点到数据点的平均线,因为它清楚地表明在跳过的日子里没有数据(例如 8/11)。
根据@Philipp Jahoda 的评论,听起来您可以跳过 0 值条目,只需将您拥有的数据索引到正确的标签即可。
我修改了 MPAndroidChart 示例程序以跳过几个数据点,结果如下:
正如@Philipp Jahoda 在评论中提到的那样,图表通过连接到下一个数据点来处理丢失的 Entry
。从下面的代码中,您可以看到我正在为整个数据集生成 x 值(标签),但跳过索引 11 - 29 的 y 值(数据点),这正是您想要的。剩下的唯一事情就是处理 x 标签,因为听起来您不希望我的示例中的 15、20 和 25 出现。
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < count; i++) {
xVals.add((i) + "");
}
ArrayList<Entry> yVals = new ArrayList<Entry>();
for (int i = 0; i < count; i++) {
if (i > 10 && i < 30) {
continue;
}
float mult = (range + 1);
float val = (float) (Math.random() * mult) + 3;// + (float)
// ((mult *
// 0.1) / 10);
yVals.add(new Entry(val, i));
}
我所做的是完全为 x 数据提供日期,甚至没有为它提供 y 数据,并且只是不添加特定 xIndex 的数据条目,然后它不会绘制 xIndex 的 y 值来实现你的目标想要,这是最简单的方法,因为您只需编写一个 for 循环,如果您在那里没有检测到 y 值,则继续。
我不建议使用0或nan,因为如果是折线图,它会连接0数据,否则nan会发生不好的事情。你可能想要换行,但是 ios-charts 还不支持它(我也为此询问了一个功能),你需要编写自己的代码来换行,或者你可以接受连接0 数据或仅连接到下一个有效数据。
缺点是性能可能会下降,因为那里有很多 xIndex,但我尝试了 ~1000,这是可以接受的。很久以前我就要求过这样的功能,但是考虑了很多时间。
对我有用的解决方案是将线数据集拆分为 2 个线数据集。首先将 yvals 保持到空 space,然后在空 space.
之后保持第二个
//create 2 LineDataSets. set1- till empty space set2 after empty space
set1 = new LineDataSet(yVals1, "DataSet 1");
set2= new LineDataSet(yVals2,"DataSet 1");
//load datasets into datasets array
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
dataSets.add(set1);
dataSets.add(set2);
//create a data object with the datasets
LineData data = new LineData(xVals, dataSets);
// set data
mChart.setData(data);
这是我根据 Wingzero 的回答编写的一个函数(我为值数组中为空的条目传递了 NaN):
func populateLineChartView(lineChartView: LineChartView, labels: [String], values: [Float]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<labels.count {
if !values[i].isNaN {
let dataEntry = ChartDataEntry(value: Double(values[i]), xIndex: i)
dataEntries.append(dataEntry)
}
}
let lineChartDataSet = LineChartDataSet(yVals: dataEntries, label: "Label")
let lineChartData = LineChartData(xVals: labels, dataSet: lineChartDataSet)
lineChartView.data = lineChartData
}
在我的应用程序中,我使用 ios-图表库(swift 替代 MPAndroidChart)。 我只需要显示带有日期和值的折线图。
现在我用这个功能来显示图表
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let lineChartDataSet = LineChartDataSet(yVals: dataEntries, label: "Items count")
let lineChartData = LineChartData(xVals: dataPoints, dataSet: lineChartDataSet)
dateChartView.data = lineChartData
}
这是我的数据:
xItems = ["27.05", "03.06", "17.07", "19.09", "20.09"] //String
let unitsSold = [25.0, 30.0, 45.0, 60.0, 20.0] //Double
但如您所见 - xItems 是 "dd.mm" 格式的日期。因为它们是字符串,所以它们彼此之间有相同的填充。我希望他们在真实日期上更准确。例如 19.09 和 20.09 应该非常接近。我知道我应该每天匹配一些数字才能完成它。但我不知道下一步该怎么做 - 如何调整 x 标签边距?
更新 经过小型研究后,我发现许多开发人员都询问过此功能但没有任何反应 - 就我而言,我在 Swift - PNChart 中找到了这个库的非常有趣的替代方案。简单易用,解决了我的问题。
最简单的解决方案是遍历您的数据并添加值为 0 的 ChartDataEntry
和每个缺失日期的相应标签。
为了回答评论中的问题,这里是我的一个应用程序的屏幕截图,我在其中用 0 值填充日期空白:
在我的例子中,我想要 0 值而不是从数据点到数据点的平均线,因为它清楚地表明在跳过的日子里没有数据(例如 8/11)。
根据@Philipp Jahoda 的评论,听起来您可以跳过 0 值条目,只需将您拥有的数据索引到正确的标签即可。
我修改了 MPAndroidChart 示例程序以跳过几个数据点,结果如下:
正如@Philipp Jahoda 在评论中提到的那样,图表通过连接到下一个数据点来处理丢失的 Entry
。从下面的代码中,您可以看到我正在为整个数据集生成 x 值(标签),但跳过索引 11 - 29 的 y 值(数据点),这正是您想要的。剩下的唯一事情就是处理 x 标签,因为听起来您不希望我的示例中的 15、20 和 25 出现。
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < count; i++) {
xVals.add((i) + "");
}
ArrayList<Entry> yVals = new ArrayList<Entry>();
for (int i = 0; i < count; i++) {
if (i > 10 && i < 30) {
continue;
}
float mult = (range + 1);
float val = (float) (Math.random() * mult) + 3;// + (float)
// ((mult *
// 0.1) / 10);
yVals.add(new Entry(val, i));
}
我所做的是完全为 x 数据提供日期,甚至没有为它提供 y 数据,并且只是不添加特定 xIndex 的数据条目,然后它不会绘制 xIndex 的 y 值来实现你的目标想要,这是最简单的方法,因为您只需编写一个 for 循环,如果您在那里没有检测到 y 值,则继续。
我不建议使用0或nan,因为如果是折线图,它会连接0数据,否则nan会发生不好的事情。你可能想要换行,但是 ios-charts 还不支持它(我也为此询问了一个功能),你需要编写自己的代码来换行,或者你可以接受连接0 数据或仅连接到下一个有效数据。
缺点是性能可能会下降,因为那里有很多 xIndex,但我尝试了 ~1000,这是可以接受的。很久以前我就要求过这样的功能,但是考虑了很多时间。
对我有用的解决方案是将线数据集拆分为 2 个线数据集。首先将 yvals 保持到空 space,然后在空 space.
之后保持第二个//create 2 LineDataSets. set1- till empty space set2 after empty space
set1 = new LineDataSet(yVals1, "DataSet 1");
set2= new LineDataSet(yVals2,"DataSet 1");
//load datasets into datasets array
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
dataSets.add(set1);
dataSets.add(set2);
//create a data object with the datasets
LineData data = new LineData(xVals, dataSets);
// set data
mChart.setData(data);
这是我根据 Wingzero 的回答编写的一个函数(我为值数组中为空的条目传递了 NaN):
func populateLineChartView(lineChartView: LineChartView, labels: [String], values: [Float]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<labels.count {
if !values[i].isNaN {
let dataEntry = ChartDataEntry(value: Double(values[i]), xIndex: i)
dataEntries.append(dataEntry)
}
}
let lineChartDataSet = LineChartDataSet(yVals: dataEntries, label: "Label")
let lineChartData = LineChartData(xVals: labels, dataSet: lineChartDataSet)
lineChartView.data = lineChartData
}