I have JSON data that I decoded and stored in core data that I am using to populate a SwiftUi line chart. I need to calculate the average of the data by dates. So the average of polling data by months.
JSON Data:
"president": "Joe Biden",
"subgroup": "All polls",
"modeldate": "9/9/2022",
"startdate": "1/19/2021",
"enddate": "1/21/2021",
"pollster": "Rasmussen Reports/Pulse Opinion Research",
"grade": "B",
"samplesize": 1500,
"population": "lv",
"weight": 0.33818752,
"influence": 0,
"approve": 48,
"disapprove": 45,
"adjusted_approve": 49.154266,
"adjusted_disapprove": 40.2849,
"multiversions": "",
"tracking": "T",
"url": "https://www.rasmussenreports.com/public_content/politics/biden_administration/biden_approval_index_history",
"poll_id": 74247,
"question_id": 139395,
"createddate": "January 2021",
"timestamp": "09:48:31 9 Sep 2022"
Data Model:
struct PresApprovalDTO: Hashable, Decodable {
var president: String
var subgroup: String
var startdate: String
var enddate: String
var pollster: String
var approve: Double
var disapprove: Double
var url: String
var createddate: String
var startDateConverter: Date {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
dateFormatter.dateFormat = "MM-dd-yyyy"
let date = dateFormatter.date(from:startdate) ?? Date()
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day, .hour], from: date)
let finalDate = calendar.date(from:components) ?? Date()
return(finalDate)
}
var endDateConverter: Date {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
dateFormatter.dateFormat = "MM-dd-yyyy"
let date = dateFormatter.date(from:enddate) ?? Date()
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day, .hour], from: date)
let finalDate = calendar.date(from:components) ?? Date()
return(finalDate)
}
}
Chart View Model:
import SwiftUI
import Charts
struct PresApprChart: View {
@StateObject private var pollListVM = PollsListViewModel()
var body: some View {
Chart(pollListVM.presPolls, id: \.url) { item in
LineMark(x: .value("Month", item.endDateConverter, unit: .month),
y: .value("Approval", item.approve)
)
}.frame(width: 325, height: 200)
.onAppear(perform: {
pollListVM.getAllPresPolls()
})
}
}
struct PresApprChart_Previews: PreviewProvider {
static var previews: some View {
PresApprChart()
}
}
Above is the result. There are tons of data points for each month, so I need to average them. I tried to map and divide the approved values by the date count, but it averages all the approval data points.
LineMark(x: .value("Month", item.endDateConverter, unit: .month),
y: .value("Approval", pollListVM.presPolls.map(\.approve).reduce(0.0, +) / Double(item.endDateConverter.asFormattedString().count))
)