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

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 с помощью {{X3 }} устный переводчик.

Какое решение этой проблемы с помощью JavaScript является эффективным ES6?

0
lys 28 Окт 2020 в 14:31

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))
})()
1
lys 1 Ноя 2020 в 03:57