I'm fairly new to using the iOS Charts library and I was able to make a bar chart, but I'm having trouble understanding how to "stack" a set of data containing the same x-axis value.
Here's what my bar chart currently looks like:
And the code to achieve this:
extension MyViewController: IAxisValueFormatter
{
func stringForValue(_ value: Double, axis: AxisBase?) -> String
{
let record_ARRAY = record_ARRAY.sorted(by: {$0.date < $1.date})
let date = record_ARRAY[Int(value)].date
return ReusableClass.typeThreeDateFormat(date: date)
}
}
var chargeDates_ARRAY = [Date]()
var chargeCosts_ARRAY = [Double]()
override func viewDidLoad()
{
chargeDates_ARRAY = [2017-08-05 07:00:00 +0000, 2017-08-06 07:00:00 +0000, 2017-08-06 07:00:00 +0000, 2017-08-07 07:00:00 +0000]
chargeCosts_ARRAY = [8.0, 3.0, 5.6600000000000001, 4.4400000000000004]
createBarChart(dataPoints: chargeDates_ARRAY, values: chargeCosts_ARRAY)
barChartView.delegate = self
}
func createBarChart(dataPoints: [Date], values: [Double])
{
var dataEntries: [BarChartDataEntry] = []
for index in 0..<dataPoints.count
{
let dataEntry = BarChartDataEntry(x: Double(index),
y: values[index])
dataEntries.append(dataEntry)
}
barChartView.xAxis.valueFormatter = self
barChartView.xAxis.granularity = 1
barChartView.xAxis.setLabelCount(dataPoints.count, force: false)
barChartView.animate(yAxisDuration: 1.0, easingOption: .easeInOutQuad)
let chartDataSet = BarChartDataSet(values: dataEntries, label: "")
let chartData = BarChartData(dataSet: chartDataSet)
barChartView.data = chartData
barChartView.zoom(scaleX: zoomXMultiplier, scaleY: 0.0, x: 0, y: 0)
barChartView.barData?.barWidth = barWidthMultiplier
}
What I like to do is combine the data containing the 2 same x-axis values 08/06/17 into one stacked bar, and achieve something like this:
I've tried to follow the answer from the question: Stacked bar chart with charts in Swift
But I couldn't get anywhere.
Can someone help? Thanks!
Try to construct your chargeCosts_ARRAY = [8.0, 3.0, 5.6600000000000001, 4.4400000000000004] as chargeCosts_ARRAY = [[8.0], [3.0, 5.6600000000000001], [4.4400000000000004]] basically you are trying to create an object of type [[Double]](). Then change BarChartDataEntry(x: Double(index), y: values[index]) to BarChartDataEntry(x: Double(index), yValues: values[index]). Happy coding :)
Related
I have an issue creating a string value for xAxis using the iOS Charts library
x value always has duplicate value, see following picture, you can see value always be JAN JAN JAN JAN FEB FEB FEB
How I can setup chart's x value as it will show JAN FEB MAR ?
import UIKit
import Charts
class ViewController: UIViewController {
var months:[String]!
#IBOutlet var lineChartView: LineChartView!
override func viewDidLoad() {
super.viewDidLoad()
let unitsSold = [20.0, 4.0, 6.0]
var months = ["Jan", "Feb", "Mar"]
let formato:LineChartFormatter = LineChartFormatter(labels: months)
let xaxis:XAxis = XAxis()
var dataEntries: [ChartDataEntry] = []
for i in 0..<unitsSold.count {
let dataEntry = ChartDataEntry(x: Double(i), y: unitsSold[i])
print("double \(Double(i))")
dataEntries.append(dataEntry)
}
xaxis.valueFormatter = formato
let data = LineChartData()
let dataset = LineChartDataSet(values: dataEntries, label: "Hello")
dataset.colors = [NSUIColor.red]
data.addDataSet(dataset)
self.lineChartView.gridBackgroundColor = NSUIColor.white
self.lineChartView.xAxis.drawGridLinesEnabled = true;
self.lineChartView.xAxis.labelPosition = XAxis.LabelPosition.bottom
self.lineChartView.xAxis.centerAxisLabelsEnabled = true
self.lineChartView.chartDescription?.text = "LineChartView Example"
self.lineChartView.xAxis.valueFormatter = xaxis.valueFormatter
self.lineChartView.data = data
}
override open func viewWillAppear(_ animated: Bool) {
self.lineChartView.animate(xAxisDuration: 1.0, yAxisDuration: 1.0)
}
}
#objc(LineChartFormatter)
public class LineChartFormatter: NSObject, IAxisValueFormatter{
var labels: [String] = []
public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
return labels[Int(value)]
}
init(labels: [String]) {
super.init()
self.labels = labels
}
}
First, use granularity to avoid duplicated values.
Second, check your valueFormatter not to return same string if you found their values are very different. e.g. int(1.5) and int(1.9) will give you same Jan but you may want to let 1.9 return Feb
Again, you have to carefully implement your own valueFormatter if you are handling decimals
add this two lines in your code
lineChartView.xAxis.granularityEnabled = true
lineChartView.xAxis.granularity = 1.0
I would like to draw radar charts with iOS Charts library by danielgindi, but I cannot figure out how to use options, especially the options regarding the axis.
It does work usually, but when I set the list of variables (array) as [100.0, 100.0, 100.0, 100.0, 100.0], it shows too zoomed a chart like this:
Instead, when I set array as [90.0, 80.0, 90.0, 70.0, 20.0], the interval of the grid lines is not 20 in spite of my code:
Judging from these outputs, the cause of the problem seems to be the options for the axis. However, I could not to solve this problem myself.
How do you fix the size of the chart and the range of the axis, and draw grid lines just as you like?
I use Xcode 8.1 / swift 2.3 / Charts 2.3.1.
import UIKit
import Charts
class ViewController: UIViewController {
#IBOutlet weak var radarChartView: RadarChartView!
//Label
let subjects = ["English", "Math", "Physics", "Chemistry", "Biology"]
//Points
let array = [100.0, 100.0, 100.0, 100.0, 100.0]
override func viewDidLoad() {
super.viewDidLoad()
setChart(subjects, values: array)
print("array:")
print(array)
}
func setChart(dataPoints: [String], values: [Double]) {
radarChartView.noDataText = "You need to provide data for the chart."
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let chartDataSet = RadarChartDataSet(yVals: dataEntries, label: "Units Sold")
let chartData = RadarChartData(xVals: subjects, dataSet: chartDataSet)
radarChartView.data = chartData
//Options of radarChart
radarChartView.sizeToFit()
radarChartView.descriptionText = ""
//Options for the axis from here. The range is 0-100, the interval is 20
radarChartView.yAxis.labelCount = 6
radarChartView.yAxis.axisMinValue = 0.0
radarChartView.yAxis.axisMaxValue = 100.0
radarChartView.rotationEnabled = false
chartDataSet.drawFilledEnabled = true
//Present the number as integer
let numberFormatter = NSNumberFormatter()
numberFormatter.generatesDecimalNumbers = false
chartDataSet.valueFormatter = numberFormatter
radarChartView.yAxis.valueFormatter = numberFormatter
//Other options
radarChartView.legend.enabled = false
radarChartView.yAxis.gridAntialiasEnabled = true
radarChartView.animate(yAxisDuration: 2.0)
}
I just had to set data AFTER options.
picture
func setChart(dataPoints: [String], values: [Double]) {
radarChartView.noDataText = "You need to provide data for the chart."
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let chartDataSet = RadarChartDataSet(yVals: dataEntries, label: "Units Sold")
//Set options...
//Then set data
let chartData = RadarChartData(xVals: subjects, dataSet: chartDataSet)
}
I added a bar chart to the storyboard, but I cannot properly set labels for my data entries.
here is my code:
var names = ["aaa", "bbb", "ccc", "ddd"]
var values = [230.0, 280.0, 450.0, 340.0]
setChart(dataPoints: names, values: values)
setChart function:
func setChart(dataPoints: [String], values: [Double])
{
let formatter = BarChartFormatter()
formatter.setValues(values: dataPoints)
let xaxis:XAxis = XAxis()
barChartView.noDataText = "You need to provide data for the chart."
var dataEntries: [BarChartDataEntry] = []
for i in 0..<dataPoints.count
{
let dataEntry = BarChartDataEntry(x: Double(i), y: values[i])
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(values: dataEntries, label: "موجودی")
let chartData = BarChartData(dataSet: chartDataSet)
xaxis.valueFormatter = formatter
barChartView.xAxis.labelPosition = .bottom
barChartView.xAxis.drawGridLinesEnabled = false
barChartView.xAxis.valueFormatter = xaxis.valueFormatter
barChartView.chartDescription?.enabled = false
barChartView.legend.enabled = true
barChartView.rightAxis.enabled = false
barChartView.data = chartData
}
and finally the formatter:
#objc(BarChartFormatter)
public class BarChartFormatter: NSObject, IAxisValueFormatter
{
var names = [String]()
public func stringForValue(_ value: Double, axis: AxisBase?) -> String
{
return names[Int(value)]
}
public func setValues(values: [String])
{
self.names = values
}
}
but it didn't work well as shown below:
as shown here, it add 6 labels instead 4 labels, and it also has duplicates.
I already read this solution, however, as you can see, it has some issues yet.
How can I solve this problem?
I think you can try to set the following properties:
barChartView.xAxis.granularityEnabled = true
barChartView.xAxis.granularity = 1.0 //default granularity is 1.0, but it is better to be explicit
barChartView.xAxis.decimals = 0
The source code tells you a lot about the properties above. https://github.com/danielgindi/Charts/blob/master/Source/Charts/Components/AxisBase.swift
I am using Daniel's IOS Chart framework and Xcode7.3.1. I went through basic tutorial and tried to set up first example.
Problem is I cannot assign X-axis string label
I see in tutorial when we assign data to chart, we should use
let chartData = BarChartData(xVals: dataPoints, dataSet: chartDataSet)
to complete last step, but below is what I am seeing here.
There is no parameter as "xVals" but only "dataset" is available.
Does anybody have idea?
The result would be just barchart without any xaxis label as below
Ok so here is example function for line chart:
func setLineChart(dataPoints: [Double], chartInfo: String, chartDescription: String) {
let formatter:ChartFormatter = ChartFormatter()
let xaxis:XAxis = XAxis()
var dataEntries: [ChartDataEntry] = Array()
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(x: Double(i), y: dataPoints[i])
dataEntries.append(dataEntry)
formatter.stringForValue(Double(i), axis: xaxis)
}
let lineChartDataSet = LineChartDataSet(values: dataEntries, label: chartInfo)
let lineChartData = LineChartData(dataSet: lineChartDataSet)
xaxis.valueFormatter = formatter
lineChartView.xAxis.valueFormatter = xaxis.valueFormatter
lineChartDataSet.mode = .CubicBezier
lineChartDataSet.drawCirclesEnabled = false
lineChartView.descriptionText = chartDescription
lineChartView.data = lineChartData
}
Here is formatter:
#objc(ChartFormatter)
public class ChartFormatter: NSObject, IAxisValueFormatter{
var days: [String] = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
public func stringForValue(value: Double, axis: AxisBase?) -> String{
return days[Int(value)]
}
}
And finally a call of function:
override func viewDidLoad() {
super.viewDidLoad()
let values: [Double] = [1.0, 4.0, 1.5, 1.4, 1.3, 1.0, 3.0]
let chartInfo = "chart info"
let chartDescription = "chart description"
self.setLineChart(values, chartInfo: chartInfo, chartDescription: chartDescription
}
so finally you will get something like this:
Seems like you are using old tutorials! Because the swift 3 is coming the the developers of these charts changed library .. according to them we will have to use special formatters to set for example values String of type to X axis. So now you have method which accepts only one parameter instead of two:
let barChartData = BarChartData(dataSet: chartDataSet)
let lineChartData = LineChartData(dataSet: lineChartDataSet)
More information you can find here:
https://github.com/danielgindi/Charts/issues/1340
I am developing one activity tracker iOS application in which I need to show a history of steps and calories in a bar chart. I used iOS Charts
for this. I am able to get the grouped charts by using this but i am not able to show two seperate axis bars for steps and calories. Below is my requirment. Please suggest me how can i achive this using iOS-Charts or suggest me any other charts written in Swift.
Grouped Bar Chart
I wrote the code using iOS Charts library as below,
func setUpDataForCharts()
{
var weekDays = [String]()
for i in 1 ... 7
{
let value = String(i)
weekDays.append(value)
}
let steps = [2000, 4000, 3500, 1300, 5000, 4800, 2400]
let calories = [20.5, 40.3, 34.0, 13.3, 50.0, 80.2, 20.0]
setChartBarGroupDataSet(weekDays, values: steps, values2: calories)
//setChart(weekDays, values: steps)
barChartView.xAxis.labelPosition = ChartXAxis.LabelPosition.Bottom
barChartView.xAxis.drawGridLinesEnabled = false
}
func setChartBarGroupDataSet(dataPoints: [String], values: [Double], values2: [Double]) {
var dataEntries: [BarChartDataEntry] = []
var dataEntries2: [BarChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = BarChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
for i in 0..<dataPoints.count {
let dataEntry = BarChartDataEntry(value: values2[i], xIndex: i)
dataEntries2.append(dataEntry)
}
let chartDataSet = BarChartDataSet(yVals: dataEntries, label: "Steps")
let chartDataSet2 = BarChartDataSet(yVals: dataEntries2, label: "Calories")
chartDataSet2.colors = [UIColor(hex: "3F7FD0")]
chartDataSet.colors = [UIColor(hex: "F53609")]
let dataSets: [BarChartDataSet] = [chartDataSet,chartDataSet2]
let data = BarChartData(xVals: dataPoints, dataSets: dataSets)
barChartView.data = data
barChartView.descriptionText = ""
barChartView.rightAxis.axisMaxValue = chartDataSet2.yMax + 1.0
barChartView.rightAxis.labelCount = chartDataSet2.valueCount
barChartView.rightAxis.drawGridLinesEnabled = true
barChartView.rightAxis.drawAxisLineEnabled = false
barChartView.rightAxis.drawLabelsEnabled = true
barChartView.animate(xAxisDuration: 2.0, yAxisDuration: 2.0, easingOption: .Linear)
}
Out put with the above code is,
Output
Thanks in advance!