Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

157
Views
Calcule max en una ventana deslizante para TimeSeries

Aporte:

 public class MyObject { public double Value { get; set; } public DateTime Date { get; set; } }

Método para generar objetos de prueba:

 public static MyObject[] GetTestObjects() { var rnd = new Random(); var date = new DateTime(2021, 1, 1, 0, 0, 0); var result = new List<MyObject>(); for (int i = 0; i < 50000; i++) { //this is to simulate real data having gaps if (rnd.Next(100) < 25) { continue; } var myObject = new MyObject() { Value = rnd.NextDouble(), Date = date.AddMinutes(15 * i) }; result.Add(myObject); } return result.ToArray(); }

Dado esto, necesito calcular el valor máximo de los 12 meses anteriores para cada myObject. Podría pensar en hacer esto InParallel, pero tal vez haya una solución optimizada.

Perdón por no estar claro, esto es lo que uso ahora mismo para obtener lo que quiero:

 public MyObject[] BruteForceBackward(MyObject[] testData) { return testData.AsParallel().Select(point => { var max = testData.Where(x => x.Date <= point.Date && x.Date >= point.Date.AddYears(-1)).Max(x => x.Value); return new MyObject() { Date = point.Date, Value = point.Value / max }; }).OrderBy(r => r.Date).ToArray(); }

Esto funciona pero es lento y consume recursos del procesador (imagínate, tienes 100k objetos), creo que debe haber algo mejor

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Suponiendo que quiere decir que necesita el Value máximo para cada uno de los últimos 12 meses desde result , entonces puede usar LINQ:

 var beginDateTime = DateTime.Now.AddMonths(-12); var ans = result.Where(r => r.Date >= beginDateTime).GroupBy(r => r.Date.Month).Select(mg => mg.MaxBy(r => r.Value)).ToList();

Ejecutando un tiempo, entiendo que poner AsParallel después del result cambia el tiempo de ejecución de alrededor de 16 ms (primera ejecución) a alrededor de 32 ms, por lo que en realidad es más lento. Es casi lo mismo después de Where y unos 23 ms después de GroupBy (procesando los 12 grupos en paralelo). Al menos en mi PC, no hay suficientes datos ni operaciones complejas para el paralelismo, pero GroupBy no es el más eficiente.

Usando una matriz y probando cada elemento, obtengo los resultados en aproximadamente 1,2 ms:

 var maxMOs = new MyObject[12]; foreach (var r in result.Where(r => r.Date >= beginDateTime)) { var monthIndex = r.Date.Month-1; if (maxMOs[monthIndex] == null || r.Value > maxMOs[monthIndex].Value) maxMOs[monthIndex] = r; }

Tenga en cuenta que los resultados no son cronológicos; puede compensar monthIndex con el mes de hoy para ordenar los resultados si lo desea.

 var maxMOs = new MyObject[12]; var offset = DateTime.Now.Month-11; foreach (var r in result.Where(r => r.Date >= beginDateTime)) { var monthIndex = r.Date.Month-offset; if (maxMOs[monthIndex] == null || r.Value > maxMOs[monthIndex].Value) maxMOs[monthIndex] = r; }

Una microoptimización (principalmente útil en ejecuciones repetidas) es invertir la prueba y usar el operador de propagación nula:

 if (!(r.Value <= maxMOs[monthIndex]?.Value))

Esto ahorra alrededor de 0,2 ms en la primera ejecución, pero hasta 0,5 ms en las ejecuciones posteriores.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!