UNPKG

austrian-cpi

Version:

Query and merge Austrian CPI time series data for economic modeling

129 lines (106 loc) 3.36 kB
import { austrianCPI } from "../austrianCPI.js"; import { parsePeriod, normalizeDate } from "./cpiUtils.js"; /** * Query CPI * @param {string} start - e.g. '2022-01' or '2022' * @param {string} end - e.g. '2023-12' or '2023' * @param {{ frequency?: 'monthly' | 'yearly', series?: string[] }} options * @returns {Array<Object>} */ function queryCPI(start, end, options) { options = options || {}; const frequency = options.frequency || "monthly"; const series = Array.isArray(options.series) ? options.series : []; const startParts = start.split("-"); const endParts = end.split("-"); const startYear = parseInt(startParts[0], 10); const startMonth = startParts.length > 1 ? parseInt(startParts[1], 10) : 1; const endYear = parseInt(endParts[0], 10); const endMonth = endParts.length > 1 ? parseInt(endParts[1], 10) : 12; const min = startYear * 100 + startMonth; const max = endYear * 100 + endMonth; const result = []; for (let i = 0; i < austrianCPI.length; i++) { const row = austrianCPI[i]; const parsed = parsePeriod(row); if (!parsed || parsed.type !== frequency) continue; const y = parsed.year; const m = parsed.month || 1; const dateKey = `${y}-${m.toString().padStart(2, "0")}`; if (dateKey < start || dateKey > end) continue; const values = {}; for (let j = 0; j < series.length; j++) { const key = series[j]; let val = row[key]; if ( val === "None" || val === undefined || val === null || typeof val === "object" ) { values[key] = null; } else if (typeof val === "string") { values[key] = parseFloat(val.replace(",", ".")); } else { values[key] = val; } } result.push(Object.assign({ date: dateKey }, values)); } return result; } /** * Convert to CSV * @param {Array<Object>} data * @returns {string} */ function exportToCSV(data) { if (!Array.isArray(data) || data.length === 0) return ""; const keys = ["date"].concat( Object.keys(data[0]).filter((k) => k !== "date"), ); const header = keys.join(","); const rows = data.map((row) => keys .map((k) => { const val = row[k]; return val !== undefined && val !== null ? val : ""; }) .join(","), ); return [header].concat(rows).join("\n"); } /** * Merge CPI into other dataset by date key * @param {Array<Object>} cpiData * @param {Array<Object>} otherData * @returns {Array<Object>} */ function mergeWith(cpiData, otherData) { const cpiMap = {}; const allKeys = new Set(); for (let i = 0; i < cpiData.length; i++) { const row = cpiData[i]; const normDate = normalizeDate(row.date); cpiMap[normDate] = row; for (const key in row) { if (key !== "date") allKeys.add(key); } } return otherData.map((row) => { const normDate = normalizeDate(row.date); const match = cpiMap[normDate]; const merged = { ...row }; allKeys.forEach((key) => { let val = match && key in match ? match[key] : null; // Warn and sanitize if (val !== null && typeof val === "object") { console.warn("Unexpected object for key:", key, "on date:", normDate); val = null; } merged[key] = val; }); return merged; }); } export { queryCPI, mergeWith, exportToCSV };