iOS-Charts grouped bar chart with size to fit - ios

I recently added "barChartData.groupBars(fromX: 0, groupSpace: 0.5, barSpace: 0.03)" to my Bar Chart so that I don't have overlapping bars and I can't figure it out how to set the width to fit (no horizontal overflow)
func setupGroupedBarChartData(values1: [String], values2: [String], barLabel1: String, barLabel2: String, barColor1: UIColor, barColor2: UIColor) -> BarChartData {
let dataValues1 = values1.flatMap{ Double($0) }
let dataValues2 = values2.flatMap{ Double($0) }
var dataEntries1: [BarChartDataEntry] = []
var dataEntries2: [BarChartDataEntry] = []
for i in 0..<dataValues1.count {
let dataEntry1 = BarChartDataEntry(x: Double(i), y: dataValues1[i])
dataEntries1.append(dataEntry1)
let dataEntry2 = BarChartDataEntry(x: Double(i), y: dataValues2[i])
dataEntries2.append(dataEntry2)
}
let chartDataSet1 = BarChartDataSet(values: dataEntries1, label: barLabel1)
chartDataSet1.colors = [barColor1]
chartDataSet1.valueTextColor = AppColors.lightText
let chartDataSet2 = BarChartDataSet(values: dataEntries2, label: barLabel2)
chartDataSet2.colors = [barColor2]
chartDataSet2.valueTextColor = AppColors.lightText
var groupedDataSet : [BarChartDataSet] = [BarChartDataSet]()
groupedDataSet.append(chartDataSet1)
groupedDataSet.append(chartDataSet2)
let barChartData = BarChartData(dataSets: groupedDataSet)
barChartData.groupBars(fromX: 0, groupSpace: 0.5, barSpace: 0.03)
//display data as integer
let format = NumberFormatter()
format.generatesDecimalNumbers = false
let formatter = DefaultValueFormatter(formatter: format)
barChartData.setValueFormatter(formatter)
return barChartData
}

You can use like this :
You calculation will be like below :
// (barWidth + barSpace) * (no.of.bars) + groupSpace = 1.00 -> interval per "group"
In your code :
barChartData.groupBars(fromX: 0, groupSpace: 0.14, barSpace: 0.03)
barChartData.barWidth = 0.4
barChartView.xAxis.axisMinimum = 0
barChartView.xAxis.axisMaximum = 23

Related

How do I draw yaxis min value as different color on certain limit?

I am using iOS Charts to draw linechart but unable to draw the same graph as shown below in the image. I tried by setting leftAxis.axisMinimum = minValue but it also not working. If the given value is minimum on certain limit it should show in red color as shown in attached image.
func setLineChartWithDateFormat(graphPoints: [GraphPoints], linePosition: CGFloat, minValue: Double = 0, fillColor: UIColor = UIColor(red: 158.0/255.0, green: 188.0/255.0, blue: 136.0/255.0, alpha: 1)) {
var referenceTimeInterval: TimeInterval = 0
if let minTimeInterval = (graphPoints.map { ($0.getDateFromDateTime?.timeIntervalSince1970 ?? 0) }).min() {
referenceTimeInterval = minTimeInterval
}
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "MMM dd"
let xValuesNumberFormatter = ChartXAxisWithFormatter(referenceTimeInterval: referenceTimeInterval, dateFormatter: formatter)
// Define chart entries
var entries = [ChartDataEntry]()
var xAxisValues = [CGFloat]()
for object in graphPoints {
let timeInterval = object.getDateFromDateTime?.timeIntervalSince1970 ?? 0
let xValue = (timeInterval - referenceTimeInterval) / (3600 * 24)
xAxisValues.append(CGFloat(xValue))
let yValue = object.price ?? 0
let entry = ChartDataEntry(x: xValue, y: yValue)
entry.setValue(object.getDateFromDateTime, forKey: "data")
entries.append(entry)
}
var minValue = xAxisValues.min()
let chartDataSet = LineChartDataSet(entries: entries, label: "BPM")
chartDataSet.fillColor = fillColor
/// Data object that encapsulates all data associated with a LineChart.
let chartData = LineChartData()
chartData.addDataSet(chartDataSet)
chartData.setDrawValues(false)
chartDataSet.drawCirclesEnabled = false
chartDataSet.mode = .linear
chartDataSet.colors = [.white]
chartDataSet.fillFormatter = LineChartFillFormatter(value: minValue ?? 0)
// let gradientColors = [gradientColor1.cgColor, gradientColor2.cgColor] as CFArray
// let colorLocations: [CGFloat] = [0.7,0.0]
// guard CGGradient.init(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: gradientColors, locations: colorLocations) != nil else {
// print("Gradient Error")
// return
// }
chartDataSet.drawFilledEnabled = true
chartDataSet.fillAlpha = 1
chartDataSet.setDrawHighlightIndicators(true)
chartDataSet.drawHorizontalHighlightIndicatorEnabled = false
// lineChart.leftAxis.axisMinimum = minValue
///x axis for chart view
let xAxis: XAxis = self.lineChart.xAxis
xAxis.labelPosition = .bottomInside
xAxis.drawGridLinesEnabled = true //true, if want x Axis grid lines
xAxis.valueFormatter = xValuesNumberFormatter
xAxis.gridColor = gridColor
xAxis.axisLineColor = gridColor
xAxis.labelFont = BSFonts.getFontWithSize(fontType: .iBMPlexSansCond, fontSize: BSFontSize.small)
xAxis.labelTextColor = axisTextColor
xAxis.labelPosition = .bottom
xAxis.spaceMin = 0.5
xAxis.drawAxisLineEnabled = false
xAxis.drawLimitLinesBehindDataEnabled = true
xAxis.granularityEnabled = true
// xAxis.granularity = 2
xAxis.labelWidth = UIDevice.current.isIPad ? 30 : 20
// xAxis.labelCount = 4
///right axis for chart view
let rightAxis: YAxis = lineChart.rightAxis
rightAxis.enabled = false
///y axis of chart view
let leftAxis: YAxis = lineChart.leftAxis
leftAxis.labelPosition = .insideChart
leftAxis.drawGridLinesEnabled = true //true, if want y axis grid lines
leftAxis.drawLabelsEnabled = true
leftAxis.gridColor = gridColor
leftAxis.axisLineColor = gridColor
leftAxis.labelFont = BSFonts.getFontWithSize(fontType: .iBMPlexSansCond, fontSize: BSFontSize.small)
leftAxis.labelTextColor = axisTextColor
leftAxis.labelPosition = .outsideChart
//leftAxis.spaceBottom = 0.3
leftAxis.drawAxisLineEnabled = false
leftAxis.labelCount = 4
/// The data for the chart
lineChart.data = chartData
lineChart.doubleTapToZoomEnabled = false
lineChart.data?.highlightEnabled = true
}

How can I show first value and last value in line Chart

I'm using charts library and i'm trying to add first value and last value on line chart graph.Please let me know how can I achieve it. I have tried customising drawValue method in linechartrenderer but didn't worked.
Here is my code
var months = ["Dec 15", "Jun 16", "Dec 16", "Jun 17", "Dec 17", "Jun 18"]
var unitsSold = [50.0, 25.0, 50.0, 75.0, 100.0, 75.0]
Viewdidload:
setChart(dataPoints: months, values: unitsSold)
Method:
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(x: Double(i), y: values[i], data: dataPoints[i] as AnyObject)
dataEntries.append(dataEntry)
}
let chartDataSet = LineChartDataSet(values: dataEntries, label: nil)
chartDataSet.setColor(UIColor(red: 53/255, green: 85/255, blue: 123/255, alpha: 1))
chartDataSet.circleRadius = 5
chartDataSet.circleHoleRadius = 2
chartDataSet.drawValuesEnabled = false
chartDataSet.drawCirclesEnabled = false
let chartData = LineChartData(dataSets: [chartDataSet])
defaultChartView.data = chartData
defaultChartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: months)
defaultChartView.xAxis.labelPosition = .bottom
defaultChartView.xAxis.drawGridLinesEnabled = false
//lineChartView.xAxis.avoidFirstLastClippingEnabled = true
defaultChartView.xAxis.axisMinimum = 0
defaultChartView.xAxis.granularity = 1
defaultChartView.rightAxis.drawAxisLineEnabled = false
defaultChartView.rightAxis.drawLabelsEnabled = false
defaultChartView.rightAxis.enabled = false
defaultChartView.leftAxis.drawAxisLineEnabled = false
defaultChartView.leftAxis.axisMinimum = 0.0
defaultChartView.leftAxis.drawLabelsEnabled = false
//lineChartView.leftAxis.drawGridLinesEnabled = false
//lineChartView.leftAxis.granularityEnabled = false
defaultChartView.pinchZoomEnabled = true
defaultChartView.doubleTapToZoomEnabled = true
defaultChartView.legend.enabled = false
defaultChartView.chartDescription?.text = " "
}
viewDidLoad:
guard let firstMonth = months.first, let lastMonth = months.last else {
return
}
let myMonths = [firstMonth, lastMonth]
guard let firstValue = unitsSold.first, let lastValue = unitsSold.last else {
return
}
let myValues = [firstValue, lastValue]
setChart(dataPoints: myMonths, values: myValues)
Solution is go to linechartrenderer file and replace drawValues method
open override func drawValues(context: CGContext)
{
guard
let dataProvider = dataProvider,
let lineData = dataProvider.lineData
else { return }
if isDrawingValuesAllowed(dataProvider: dataProvider)
{
var dataSets = lineData.dataSets
let phaseY = animator.phaseY
var pt = CGPoint()
for i in 0 ..< dataSets.count
{
guard let dataSet = dataSets[i] as? ILineChartDataSet else { continue }
if !shouldDrawValues(forDataSet: dataSet)
{
continue
}
let valueFont = dataSet.valueFont
guard let formatter = dataSet.valueFormatter else { continue }
let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency)
let valueToPixelMatrix = trans.valueToPixelMatrix
let iconsOffset = dataSet.iconsOffset
// make sure the values do not interfear with the circles
var valOffset = Int(dataSet.circleRadius * 1.75)
if !dataSet.isDrawCirclesEnabled
{
valOffset = valOffset / 2
}
_xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator)
for j in stride(from: _xBounds.min, through: min(_xBounds.min + _xBounds.range, _xBounds.max), by: 1)
{
guard let e = dataSet.entryForIndex(j) else { break }
if(j == 0 || j == dataSet.entryCount - 1)
{
pt.x = CGFloat(e.x)
pt.y = CGFloat(e.y * phaseY)
pt = pt.applying(valueToPixelMatrix)
if (!viewPortHandler.isInBoundsRight(pt.x))
{
break
}
if (!viewPortHandler.isInBoundsLeft(pt.x) || !viewPortHandler.isInBoundsY(pt.y))
{
continue
}
if dataSet.isDrawValuesEnabled {
ChartUtils.drawText(
context: context,
text: formatter.stringForValue(
e.y,
entry: e,
dataSetIndex: i,
viewPortHandler: viewPortHandler),
point: CGPoint(
x: pt.x,
y: pt.y - CGFloat(valOffset) - valueFont.lineHeight),
align: .center,
attributes: [NSAttributedStringKey.font: valueFont, NSAttributedStringKey.foregroundColor: dataSet.valueTextColorAt(j)])
}
if let icon = e.icon, dataSet.isDrawIconsEnabled
{
ChartUtils.drawImage(context: context,
image: icon,
x: pt.x + iconsOffset.x,
y: pt.y + iconsOffset.y,
size: icon.size)
}
}
else{
}
}
}
}
}
Set below property of X axis
barChartView.xAxis.setLabelCount(2, force: true)

ios charts not displaying line/bar in charts

I am working on ios-charts by Daniel Gindi on swift 3.0. I have written following code for bar charts
var dataEntries: [BarChartDataEntry] = []
for i in 0..<dateTime.count {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy hh:mm:ss aa"
let dateObj = dateFormatter.date(from: dateTime[i])
let timeIntervalForDate = dateObj!.timeIntervalSince1970
let dataEntry = BarChartDataEntry(x: Double(timeIntervalForDate), y: Double(readings[i]))
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Units")
let chartData = BarChartData(dataSet: chartDataSet)
self.ChartsView.data = chartData
i get following result in emulator:
you can see no red line reflecing my values. I even zoomed to charts but nothing was shown.
I also tried line chart with sample values. Here is the code:
let dollars1 = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0, 4.0, 18.0, 2.0, 4.0, 5.0, 4.0]
let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
var yValues : [ChartDataEntry] = [ChartDataEntry]()
for i in 0 ..< months.count {
yValues.append(ChartDataEntry(x: Double(i + 1), y: dollars1[i]))
}
let LineData = LineChartData()
let ds = LineChartDataSet(values: yValues, label: "Months")
LineData.addDataSet(ds)
self.ChartsView.data = LineData
Its result is even more weird. No grid lines are shown either in this chart. Here is the image.
I am not sure what is wrong with these graphs. Am I missing something. So far i am unable to look any furthur as most solutions are using old version of charts(or may be it is something else i am not aware). Please guide me to proper direction. Thanks
I am struggling with Version 3.0 and Swift 3 and the lack of documentation... May I point you to the best text on the subject which can be found here
Xvals as Parameters are gone, instead you use two-dimensional data on axis
Regarding your problem with timevalues.. you could use the "timeIntervalSince1970" of the date-object and format things with an extension
return dateFormatter.string(from: Date(timeIntervalSince1970: value))
all of which is to be found at the link mentioned above
There is a bug in ios-charts try to use index of timestamp rather than using timestamp or date to show on the x-axis.
// i is the index of that timestamp in data.
let dataEntry = BarChartDataEntry(x: i, y: Double(readings[i]))
hey nothing is disabled in iOS charts everything is working fine..Here is the code that I have used in my app to display horizontal chart as well as vertical chart hope it helps to anyone who is stucked on IOS chart...stay tune with StackOverflow... enjoy coding :)
import UIKit
import Charts
class DashboardViewController: UIViewController, ChartViewDelegate
{
#IBOutlet weak var barview: BarChartView!
#IBOutlet weak var horizontalview: HorizontalBarChartView!
var attendencelabels = [String]()
let Present = [60.0, 60.0]
let Absent = [20.0,40.0]
var subjects : [String]!
var maxUnits : Double!
override func viewDidLoad() {
super.viewDidLoad()
barview.delegate = self
barview.noDataText = "You need to provide data for the chart."
barview.chartDescription?.text = ""
attendencelabels.append("March")
attendencelabels.append("April")
subjects = ["Physics","Chemistry","Biology","English","Maths"]
horizontalview.delegate = self
var marks = [60.0,70.0,60.0,80.0,90.0]
maxUnits = marks.max()
setHorizontalChart(dataPoints: subjects, values: marks)
//legend
let legend = barview.legend
legend.enabled = true
legend.horizontalAlignment = .center
legend.verticalAlignment = .bottom
legend.orientation = .horizontal
legend.drawInside = false
legend.yOffset = 10.0;
legend.xOffset = 10.0;
legend.yEntrySpace = 0.0;
let xaxis = barview.xAxis
xaxis.valueFormatter = DefaultAxisValueFormatter.self as! IAxisValueFormatter
xaxis.drawGridLinesEnabled = true
xaxis.labelPosition = .top
xaxis.centerAxisLabelsEnabled = true
xaxis.valueFormatter = IndexAxisValueFormatter(values:self.attendencelabels)
xaxis.granularity = 1
let leftAxisFormatter = NumberFormatter()
leftAxisFormatter.maximumFractionDigits = 1
let yaxis = barview.leftAxis
yaxis.spaceTop = 0.35
yaxis.axisMinimum = 0
yaxis.drawGridLinesEnabled = false
barview.rightAxis.enabled = false
setChart()
}
func setChart() {
barview.noDataText = "You need to provide data for the chart."
var dataEntries: [BarChartDataEntry] = []
var dataEntries1: [BarChartDataEntry] = []
for i in 0..<self.attendencelabels.count
{
let dataEntry = BarChartDataEntry(x: Double(i) , y: self.Present[i])
dataEntries.append(dataEntry)
let dataEntry1 = BarChartDataEntry(x: Double(i) , y: self.self.Absent[i])
dataEntries1.append(dataEntry1)
//stack barchart
//let dataEntry = BarChartDataEntry(x: Double(i), yValues: [self.unitsSold[i],self.unitsBought[i]], label: "groupChart")
}
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Working Days")
let chartDataSet1 = BarChartDataSet(values: dataEntries1, label: "Present Days")
let dataSets: [BarChartDataSet] = [chartDataSet,chartDataSet1]
chartDataSet.colors = [UIColor(red: 0/255, green: 255/255, blue: 25/255, alpha: 1)]
chartDataSet1.colors = [UIColor(red: 255/255, green: 0/255, blue: 61/255, alpha: 1)]
//chartDataSet.colors = ChartColorTemplates.colorful()
//let chartData = BarChartData(dataSet: chartDataSet)
let chartData = BarChartData(dataSets: dataSets)
let groupSpace = 0.3
let barSpace = 0.05
let barWidth = 0.3
// (0.3 + 0.05) * 2 + 0.3 = 1.00 -> interval per "group"
let groupCount = self.attendencelabels.count
let startYear = 0
chartData.barWidth = barWidth;
barview.xAxis.axisMinimum = Double(startYear)
let gg = chartData.groupWidth(groupSpace: groupSpace, barSpace: barSpace)
print("Groupspace: \(gg)")
barview.xAxis.axisMaximum = Double(startYear) + gg * Double(groupCount)
chartData.groupBars(fromX: Double(startYear), groupSpace: groupSpace, barSpace: barSpace)
//chartData.groupWidth(groupSpace: groupSpace, barSpace: barSpace)
barview.notifyDataSetChanged()
barview.data = chartData
//background color
barview.backgroundColor = UIColor.white
//chart animation
barview.animate(xAxisDuration: 1.5, yAxisDuration: 1.5, easingOption: .linear)
}
func setHorizontalChart(dataPoints: [String], values: [Double]) {
horizontalview.noDataText = "You need to provide data for the chart."
let formato: horizontalbarformatter = horizontalbarformatter()
let xaxiss: XAxis = XAxis()
var dataEntriesss: [BarChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntryy = BarChartDataEntry(x: Double(Int(i)), y: values[i])
dataEntriesss.append(dataEntryy)
formato.stringForValue(Double(i), axis: xaxiss)
}
xaxiss.valueFormatter = formato
let chartHorizontalDataSet = BarChartDataSet(values: dataEntriesss, label: "Marks")
let horizontalchartData = BarChartData(dataSet: chartHorizontalDataSet)
chartHorizontalDataSet.colors = ChartColorTemplates.colorful()
horizontalview.xAxis.valueFormatter = xaxiss.valueFormatter
horizontalview.data = horizontalchartData
horizontalview.backgroundColor = UIColor.white
horizontalview.descriptionText = ""
horizontalview.xAxis.labelPosition = .bottom
horizontalview.leftAxis.axisMinimum = 0
horizontalview.leftAxis.axisMaximum = maxUnits + 1
//barChartView.animate(xAxisDuration: 2.0, yAxisDuration: 2.0)
horizontalview.animate(xAxisDuration: 2.0, yAxisDuration: 2.0, easingOption: .easeInBounce)
let ll = ChartLimitLine(limit: 10.0, label: "Target")
horizontalview.rightAxis.addLimitLine(ll)
}
func chartValueSelected(chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
print("\(entry.y) in \(attendencelabels[Int(entry.x)])")
}
}

iOS Charts -> Last value doesn't appear

I have some troubles with the library, when I create a barChart I have to add an extra value to my values array in order to show all my original values, and in the lineChart the last value appears in the line graph but it doesn't have its value above the point like the others.
I let you my code and some pictures showing the problem:
BarChart: My xAxis have a custom format showing months.
override func viewDidLoad() {
super.viewDidLoad()
let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0, 4.0, 18.0, 2.0, 4.0, 5.0, 4.0]
max = unitsSold.maxElement()
setChart(unitsSold)
}
func setChart(values: [Double]) {
let formato:BarChartFormatter = BarChartFormatter()
let xaxis:XAxis = XAxis()
barChartView.noDataText = "You need to provide data for the chart."
var dataEntries: [BarChartDataEntry] = []
for i in 0..<values.count {
let dataEntry = BarChartDataEntry(x: Double(i), y:values[i])
dataEntries.append(dataEntry)
formato.stringForValue(Double(i), axis: xaxis)
}
xaxis.valueFormatter = formato
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Units Sold")
chartDataSet.colors = ChartColorTemplates.joyful()
barChartView.fitBars = true //Para que las barras inicial y final se muestren completas
barChartView.xAxis.valueFormatter = xaxis.valueFormatter
barChartView.xAxis.labelPosition = .Bottom
barChartView.leftAxis.axisMinimum = 0
barChartView.leftAxis.axisMaximum = max + 2
barChartView.rightAxis.enabled = false
barChartView.drawValueAboveBarEnabled = false
barChartView.descriptionText = ""
barChartView.xAxis.drawGridLinesEnabled = false
barChartView.animate(xAxisDuration: 1.0, yAxisDuration: 1.0)
let chartData = BarChartData()
chartData.addDataSet(chartDataSet)
barChartView.data = chartData
}
LineChart: My xAxis have a custom format showing months.
override func viewDidLoad() {
super.viewDidLoad()
let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0]
max = unitsSold.maxElement()
setChart(unitsSold)
}
func setChart(values: [Double]) {
let formato:BarChartFormatter = BarChartFormatter()
let xaxis:XAxis = XAxis()
var dataEntries: [ChartDataEntry] = []
for i in 0..<values.count {
let dataEntry = ChartDataEntry(x: Double(i), y: values[i])
dataEntries.append(dataEntry)
formato.stringForValue(Double(i), axis: xaxis)
}
xaxis.valueFormatter = formato
let lineChartDataSet = LineChartDataSet(values: dataEntries, label: "Units Sold")
lineChartDataSet.colors = ChartColorTemplates.joyful()
lineChartDataSet.circleColors = ChartColorTemplates.joyful()
lineChartDataSet.drawCircleHoleEnabled = false
let lineChartData = LineChartData( dataSet: lineChartDataSet)
lineChartData.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 7))
lineChartView.fitScreen()
lineChartView.xAxis.labelPosition = .Bottom
lineChartView.xAxis.axisMaximum = Double(values.count)
lineChartView.leftAxis.axisMinimum = 0
lineChartView.leftAxis.axisMaximum = max + 3
lineChartView.rightAxis.enabled = false
lineChartView.descriptionText = ""
lineChartView.xAxis.drawGridLinesEnabled = false
lineChartView.animate(xAxisDuration: 1.0, yAxisDuration: 1.0)
lineChartView.xAxis.valueFormatter = xaxis.valueFormatter
lineChartView.data = lineChartData
}
The responses are: For barChart December doesn't appear and in lineChart the last value doesn't show its value above it, I hope someone can help.

How to make a grouped BarChart with ios-charts?

I am using ios-charts library.
I would like to group my inverter values so that each year is one group. Unfortunately, the number of monthly values per year may vary.
My data json looks like this:
{"monthlyData":[{"ERTRAG":"30.2989999055862","MONAT":"2","JAHR":"2016"},{"ERTRAG":"154.897000223398","MONAT":"1","JAHR":"2016"},{"ERTRAG":"141.996000155807","MONAT":"12","JAHR":"2015"},{"ERTRAG":"135.449000149965","MONAT":"11","JAHR":"2015"},{"ERTRAG":"319.437000751495","MONAT":"10","JAHR":"2015"},{"ERTRAG":"483.369997739792","MONAT":"9","JAHR":"2015"},{"ERTRAG":"698.112997770309","MONAT":"8","JAHR":"2015"},{"ERTRAG":"771.764000892639","MONAT":"7","JAHR":"2015"},{"ERTRAG":"736.611003398895","MONAT":"6","JAHR":"2015"},{"ERTRAG":"737.237999916077","MONAT":"5","JAHR":"2015"},{"ERTRAG":"720.181995391846","MONAT":"4","JAHR":"2015"},{"ERTRAG":"484.979001283646","MONAT":"3","JAHR":"2015"},{"ERTRAG":"249.974001646042","MONAT":"2","JAHR":"2015"},{"ERTRAG":"92.8830004036427","MONAT":"1","JAHR":"2015"},{"ERTRAG":"52.7970000207424","MONAT":"12","JAHR":"2014"},{"ERTRAG":"181.025999426842","MONAT":"11","JAHR":"2014"},{"ERTRAG":"332.789002537727","MONAT":"10","JAHR":"2014"},{"ERTRAG":"482.244999885559","MONAT":"9","JAHR":"2014"},{"ERTRAG":"602.811999320984","MONAT":"8","JAHR":"2014"},{"ERTRAG":"699.872003316879","MONAT":"7","JAHR":"2014"},{"ERTRAG":"828.212007522583","MONAT":"6","JAHR":"2014"},{"ERTRAG":"679.010004997253","MONAT":"5","JAHR":"2014"},{"ERTRAG":"635.115998744965","MONAT":"4","JAHR":"2014"},{"ERTRAG":"559.617002010345","MONAT":"3","JAHR":"2014"},{"ERTRAG":"265.135001063347","MONAT":"2","JAHR":"2014"},{"ERTRAG":"165.272998273373","MONAT":"1","JAHR":"2014"},{"ERTRAG":"134.578999936581","MONAT":"12","JAHR":"2013"},{"ERTRAG":"153.774000287056","MONAT":"11","JAHR":"2013"},{"ERTRAG":"321.733997344971","MONAT":"10","JAHR":"2013"},{"ERTRAG":"482.768000483513","MONAT":"9","JAHR":"2013"},{"ERTRAG":"692.864000797272","MONAT":"8","JAHR":"2013"},{"ERTRAG":"846.429007053375","MONAT":"7","JAHR":"2013"},{"ERTRAG":"709.758005619049","MONAT":"6","JAHR":"2013"},{"ERTRAG":"532.493996858597","MONAT":"5","JAHR":"2013"},{"ERTRAG":"462.539998054504","MONAT":"4","JAHR":"2013"},{"ERTRAG":"419.105004012585","MONAT":"3","JAHR":"2013"},{"ERTRAG":"143.189998820424","MONAT":"2","JAHR":"2013"},{"ERTRAG":"78.720000628382","MONAT":"1","JAHR":"2013"},{"ERTRAG":"90.1430006623268","MONAT":"12","JAHR":"2012"},{"ERTRAG":"155.483000457287","MONAT":"11","JAHR":"2012"},{"ERTRAG":"348.231998205185","MONAT":"10","JAHR":"2012"},{"ERTRAG":"598.037001848221","MONAT":"9","JAHR":"2012"},{"ERTRAG":"729.740003108978","MONAT":"8","JAHR":"2012"},{"ERTRAG":"676.923998832703","MONAT":"7","JAHR":"2012"},{"ERTRAG":"694.879002094269","MONAT":"6","JAHR":"2012"},{"ERTRAG":"811.281997680664","MONAT":"5","JAHR":"2012"},{"ERTRAG":"489.765002369881","MONAT":"4","JAHR":"2012"},{"ERTRAG":"538.866001605988","MONAT":"3","JAHR":"2012"},{"ERTRAG":"277.856996208429","MONAT":"2","JAHR":"2012"},{"ERTRAG":"155.854999214411","MONAT":"1","JAHR":"2012"},{"ERTRAG":"148.157999750227","MONAT":"12","JAHR":"2011"},{"ERTRAG":"230.409998774529","MONAT":"11","JAHR":"2011"}]}
I tried the following:
var months = Array<String>()
var years = Array<String>()
var dataEntries: [BarChartDataEntry] = []
var dataSets: [BarChartDataSet] = []
var overallSum = 0.0
var year = 2010 //monthlyValues[0].year
var count = 0
var chartDataSet: BarChartDataSet?
for i in 0..<monthlyValues.count {
// if year is different, create new barchartdataset
if monthlyValues[i].year != year {
years.append("\(monthlyValues[i].year)")
chartDataSet = BarChartDataSet(yVals: dataEntries, label: "\(year)")
chartDataSet!.colors = [UIColor.whiteColor()]
dataSets.append(chartDataSet!)
year = monthlyValues[i].year
dataEntries = []
//months = []
count = 0
}
months.append("\(monthlyValues[i].month)")
overallSum += monthlyValues[i].amount
let dataEntry = BarChartDataEntry(value: monthlyValues[i].amount, xIndex: count)
count++
dataEntries.append(dataEntry)
}
let chartData = BarChartData(xVals: months, dataSets: dataSets)
self.barChartView.data = chartData
This results in five series with the right year labels in the legend but there is no group separator in the chart and also the number of bars per year is either 4 or 5 (expected = 12).
Thanks for any hint on this!
let months = ["Jan", "Feb", "Mar", "Apr", "May"]
let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0]
let unitsBought = [10.0, 14.0, 60.0, 13.0, 2.0]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
barChartView.delegate = self
barChartView.noDataText = "You need to provide data for the chart."
barChartView.chartDescription?.text = "sales vs bought "
//legend
let legend = barChartView.legend
legend.enabled = true
legend.horizontalAlignment = .right
legend.verticalAlignment = .top
legend.orientation = .vertical
legend.drawInside = true
legend.yOffset = 10.0;
legend.xOffset = 10.0;
legend.yEntrySpace = 0.0;
let xaxis = barChartView.xAxis
xaxis.valueFormatter = axisFormatDelegate
xaxis.drawGridLinesEnabled = true
xaxis.labelPosition = .bottom
xaxis.centerAxisLabelsEnabled = true
xaxis.valueFormatter = IndexAxisValueFormatter(values:self.months)
xaxis.granularity = 1
let leftAxisFormatter = NumberFormatter()
leftAxisFormatter.maximumFractionDigits = 1
let yaxis = barChartView.leftAxis
yaxis.spaceTop = 0.35
yaxis.axisMinimum = 0
yaxis.drawGridLinesEnabled = false
barChartView.rightAxis.enabled = false
//axisFormatDelegate = self
setChart()
}
func setChart() {
barChartView.noDataText = "You need to provide data for the chart."
var dataEntries: [BarChartDataEntry] = []
var dataEntries1: [BarChartDataEntry] = []
for i in 0..<self.months.count {
let dataEntry = BarChartDataEntry(x: Double(i) , y: self.unitsSold[i])
dataEntries.append(dataEntry)
let dataEntry1 = BarChartDataEntry(x: Double(i) , y: self.self.unitsBought[i])
dataEntries1.append(dataEntry1)
//stack barchart
//let dataEntry = BarChartDataEntry(x: Double(i), yValues: [self.unitsSold[i],self.unitsBought[i]], label: "groupChart")
}
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Unit sold")
let chartDataSet1 = BarChartDataSet(values: dataEntries1, label: "Unit Bought")
let dataSets: [BarChartDataSet] = [chartDataSet,chartDataSet1]
chartDataSet.colors = [UIColor(red: 230/255, green: 126/255, blue: 34/255, alpha: 1)]
//chartDataSet.colors = ChartColorTemplates.colorful()
//let chartData = BarChartData(dataSet: chartDataSet)
let chartData = BarChartData(dataSets: dataSets)
let groupSpace = 0.3
let barSpace = 0.05
let barWidth = 0.3
// (0.3 + 0.05) * 2 + 0.3 = 1.00 -> interval per "group"
let groupCount = self.months.count
let startYear = 0
chartData.barWidth = barWidth;
barChartView.xAxis.axisMinimum = Double(startYear)
let gg = chartData.groupWidth(groupSpace: groupSpace, barSpace: barSpace)
print("Groupspace: \(gg)")
barChartView.xAxis.axisMaximum = Double(startYear) + gg * Double(groupCount)
chartData.groupBars(fromX: Double(startYear), groupSpace: groupSpace, barSpace: barSpace)
//chartData.groupWidth(groupSpace: groupSpace, barSpace: barSpace)
barChartView.notifyDataSetChanged()
barChartView.data = chartData
//background color
barChartView.backgroundColor = UIColor(red: 189/255, green: 195/255, blue: 199/255, alpha: 1)
//chart animation
barChartView.animate(xAxisDuration: 1.5, yAxisDuration: 1.5, easingOption: .linear)
}
You got something wrong here. Right now you are creating a new DataSet for every year.
What you need to do is create as many DataSets as you want bars per group where one DataSet represents one bar in each group. (e.g. DataSet 1 represents every first bar of a group, DataSet 2 every second bar of a group, ...)
As an example, imagine a chart like this with 4 groups of 3 bars per group. Each group represents one year.
||| ||| ||| |||
The setup shown above requires 3 DataSets (one for each group)
Entries in the same group have the same x-index (e.g. in the first group all have x-index 0)
It consists of a total of 12 entries
Each DataSet contains 4 entries with Entry x-indices ranging from 0 to 3
Here you can find an example of the scenario described above and check out the documentation.
if you have noticed in above code in function chart. There is let
groupSpace = 0.3
let barSpace = 0.05
let barWidth = 0.3
// (0.3 + 0.05) * 2 + 0.3 = 1.00 -> interval per "group"
which will make equation
(groupSpace * barSpace) * n + groupSpace = 1
you need to play around this equation for n number of bars
I've tried Rajan Twanabashu solution, but it was almost the good one. Maybe it has changed since, I don't know.
Here's what I've done, after I found the groupWidth function in the BarDataChart file from Charts.
groupWidth function declaration
let groupSpace = 1 - n * (barWidth + barSpace)
Hope it could help
After diving in this equation "(0.3 + 0.05) * 2 + 0.3 = 1.00" to work on variant amount of grouping I got:
let n = Double(data.dataSets.count)
let groupSpace = 0.0031 * n
let barSpace = 0.002 * n
let barWidth = (1 - (n * barSpace) - groupSpace) / n
What is varying is barWidth.

Resources