Нормализация значений для всех ключей во вложенных словарях и добавление новых пар ключ/значение

Скажем, у меня есть словарь с вложенными подсловарями:

let dict = 
{
    "SEATTLE" :     {
        "gross_sales" : 106766,
        "price" : 584.50,
        "dates" : [             {
                "date" : "2020-03-13",
                "total_sales_to_date" : 2,
                "new_sales" : 2,
            }
,           {
                "date" : "2020-03-19",
                "total_sales_to_date" : 5,
                "new_sales" : 3,
            }
 ]
    }
,   
    "PHOENIX" :     {
        "gross_sales" : 26691.5,
        "price" : 292.25,
        "dates" : [             {
                "date" : "2020-03-13",
                "total_sales_to_date" : 9,
                "new_sales" : 9,
            }
,           {
                "date" : "2020-03-19",
                "total_sales_to_date" : 19,
                "new_sales" : 10,
            }
 ]
    }

}

И я хотел бы нормализовать каждое числовое значение в парах ключ/значение по отношению к другим ключам/значениям, а затем добавить их как новые пары ключ/значение.

Для массива dates данных временных рядов я хотел бы нормализовать каждую пару ключ/значение в каждой дате как по времени (внутри массива), так и по другим местоположениям в ту же дату (другие объекты).

Например, это то, что я ищу после операции:

{
    "SEATTLE" :     {
        "gross_sales" : 106766,
        "normalised_gross_sales" : 1.0,
        "price" : 584.50,
        "normalised_price" : 1.0, 
        "dates" : [             {
                "date" : "2020-03-13",
                "total_sales_to_date" : 2,
                "norm_total_sales_over_time" : 0.4, 
                "norm_total_sales_over_locations" : 0.22222222, 
                "new_sales" : 2,
            }
,           {
                "date" : "2020-03-19",
                "total_sales_to_date" : 5,
                "norm_total_sales_over_time" : 1.0, 
                "norm_total_sales_over_locations" : 0.26315789, 
                "new_sales" : 3,
            }
 ]
    }
,   
    "PHOENIX" :     {
        "gross_sales" : 26691.5,
        "normalised_gross_sales" : 0.25,
        "price" : 292.25,
        "normalised_price" : 0.5,  
        "dates" : [             {
                "date" : "2020-03-13",
                "total_sales_to_date" : 9,
                "norm_total_sales_over_time" : 0.47368421, 
                "norm_total_sales_over_locations" : 1.0, 
                "new_sales" : 9,
            }
,           {
                "date" : "2020-03-19",
                "total_sales_to_date" : 19,
                "norm_total_sales_over_time" : 1.0, 
                "norm_total_sales_over_locations" : 1.0, 
                "new_sales" : 10,
            }
 ]
    }

}

то есть: значение total_sales_to_date для последней даты в массиве должно нормализоваться до 1.0 как norm_total_sales_over_time

и наибольшее значение total_sales_to_date для всех объектов (SEATTLE, PHOENIX) для текущей даты в массиве должно нормализоваться до 1,0 как norm_total_sales_over_locations

Я нахожу это очень сложным для обработки в JS. Моя фактическая задача связана со словарями с сотнями подсловарей, которые мне нужно сравнить, я ищу масштабируемое решение. В pandas dataframe это было бы тривиально, однако я хотел бы узнать, как подойти к этому, используя современный javascript, поскольку я запускаю этот процесс из node.js с помощью интерпретатора ES6.

Каково эффективное решение ES6 javascript для этого?


person lys    schedule 28.10.2020    source источник
comment
@JaredSmith - не могли бы вы уточнить? чтобы помочь мне лучше всего отредактировать вопрос   -  person lys    schedule 01.11.2020


Ответы (1)


Вот решение, которое возвращает нормализованные значения описанным образом:

let dict = {
  "SEATTLE": {
    "gross_sales": 106766,
    "price": 584.50,
    "dates": [{
      "date": "2020-03-13",
      "total_sales_to_date": 2,
      "new_sales": 2,
    }, {
      "date": "2020-03-19",
      "total_sales_to_date": 5,
      "new_sales": 3,
    }]
  },
  "PHOENIX": {
    "gross_sales": 26691.5,
    "price": 292.25,
    "dates": [{
      "date": "2020-03-13",
      "total_sales_to_date": 9,
      "new_sales": 9,
    }, {
      "date": "2020-03-19",
      "total_sales_to_date": 19,
      "new_sales": 10,
    }]
  }

}


async function normaliseDict(_dict) {

  let values = await Object.values(_dict);
  // make arrays with values from each key
  let all_gross_sales = [];
  let all_price = [];
  let all_total_sales = {};

  values.forEach((element) => {
    all_gross_sales.push(element.gross_sales);
    all_price.push(element.price);

    let most_recent_total_sales_value = element.dates[element.dates.length - 1].total_sales_to_date;

    element.dates.forEach((date, idx) => {
      date.norm_total_sales_over_time = date.total_sales_to_date / most_recent_total_sales_value;
      if (all_total_sales[date.date]) all_total_sales[date.date].push(date.total_sales_to_date);
      else {
        all_total_sales[date.date] = [];
        all_total_sales[date.date].push(date.total_sales_to_date);
      }
    });

  });

  const newDict = values.map(ob => {
    ob.gross_sales_norm = ob.gross_sales / Math.max(...all_gross_sales);
    ob.price_norm = ob.price / Math.max(...all_price);
    return ob;
  });

  values.forEach((element) => {
    element.dates.forEach((date, idx) => {
      date.norm_total_sales_over_locations_for_this_date = date.total_sales_to_date / Math.max(...all_total_sales[date.date]);
    });
  });
  return await dict;
}


(async () => {
  console.log(await normaliseDict(dict))
})()

person lys    schedule 01.11.2020