close Warning: Can't synchronize with repository "(default)" (/var/svn/tolp does not appear to be a Subversion repository.). Look in the Trac log for more information.

Opened 13 years ago

Closed 13 years ago

Last modified 13 years ago

#1518 closed defect (invalid)

DatCh returns a wrong Series

Reported by: imendez Owned by: Víctor de Buen Remiro
Priority: high Milestone: Mantainance
Component: Kernel Version: 3.1
Severity: critical Keywords:
Cc: atorre@…, jgallardo@…, atorre@…

Description

Hi, when executing this code:

Serie sr_1 = SubSer(Rand(4, 8, Daily), y2011, y2011m12d31);
Serie sr_d = DatCh(sr_1, D(31), FirstS);

sr_d begins at y2010m12d31, while sr_1 starts at y2011m01d01. How can it be possible?

Regards.

Change History (21)

comment:1 Changed 13 years ago by Víctor de Buen Remiro

It's wrong and seems to be wrong at least since version 1.1.7
Simply nobody has noticed it before you.
It will be fixed in next release.

comment:2 Changed 13 years ago by Víctor de Buen Remiro

Resolution: fixed
Status: newclosed

(In [4604]) Fixes #1518

comment:3 Changed 13 years ago by Víctor de Buen Remiro

(In [4605]) Fixes #1518 in trunk

comment:4 Changed 13 years ago by Víctor de Buen Remiro

Resolution: fixed
Status: closedreopened

Los siguientes tickets son incompatibles con este cambio: #130, #154, #526.

Estos otros también fallan aunque no afecta al problema original del ticket: #307, #457, #472.

Es cierto que el problema del DatCh con las fechas iniciales puede estar causando problemas sin que se percate nadie. Por ejemplo si tienes un cambio con SumS de fechado de diario a mensual y el primer mes sólo hay 4 días te saldrá un valor demasiado bajo que puede llevar a errores de análisis. Si son 25 días con AvrS el problema será menor y si es con LastS no habrá ningún problema.

Lo que pasa es que DatCh no conoce la semántica del estadístico por lo que tiene que obrar de forma congruente en todos los casos.

Ahora mismo si hay omitidos por el medio de la serie o bien faltan días por el final el DatCh devuelve el estadístico correspondiente a los datos conocidos obviando los omitidos, por lo que lo en la fecha inicial debe hacer lo mismo.

Así pues se restaurará el comportamiento anterior y se declarará inválido este ticket.

Si alquien quiere hacer algo distinto siempre puede usar SubSer sobre la serie antes de hacer el DatCh

Si se quiere paliar el problema de datos incompletos se sugiere completarlos mediante interpolación o previsión antes de aplicar DatCh

comment:5 Changed 13 years ago by Víctor de Buen Remiro

He aquí unos ejemplos que ilustran cómo el comportamiento de DatCh es congruente en el tratamiento de omitidos y cómo se pueden obtener otros resultados si se necesitan otros comportamientos distintos:

//Serie diaria con omitidos
Serie s = IfSer(Step(y2010m05d03,C)-Step(y2010m05d25),?,
  SubSer(Rand(0,1,C),y2010m01d15,y2011m12d15));
//Media mensual sin tener en cuenta omitidos
Serie s.avrs.1 = DatCh(s,Mensual,AvrS);
//Media mensual contando los omitidos como ceros
Serie s.avrs.2 = DatCh(s,Mensual,SumS)/CalVar(C,Mensual);
//Media mensual con omitidos en los meses donde hay omitidos en diario
Serie s.avrs.3 = 
{
  Serie zero = CalInd(C,C)*0;
  Serie s.ext = SubSer(zero,y2009m11d30,y2009m12)<<
                s>>
                SubSer(zero,y2012m02,y2012m02d02);
  Serie s.unk = GT(DatCh(IsUnknown(s.ext),Mensual,SumS),0);
  IfSer(s.unk,?,s.avrs.1)
};

comment:6 Changed 13 years ago by Víctor de Buen Remiro

Resolution: invalid
Status: reopenedclosed

comment:7 Changed 13 years ago by Víctor de Buen Remiro

(In [4659]) Refs #1518

comment:8 Changed 13 years ago by Víctor de Buen Remiro

(In [4660]) Refs #1518

comment:9 Changed 13 years ago by Alfredo Torre

Cc: atorre@… added

Hola!

En qué versión está corregido?

Yo estoy con la "v3.1 p013 2012-07-04 09:27:59 i686-win" y sigue igual.

Gracias por adelantado!

comment:10 Changed 13 years ago by Víctor de Buen Remiro

Creo que me expliqué mal. Al principio te di la razón e hice un cambio para que hiciera lo que tú querías porque me pareció de lo más natural, igual que a tí, pues a primera vista parece que se ha inventado datos por el principio.

Pero luego descubrí que el cambio era incompatible con diversos tickets anteriores y que en realidad no había nada mal. Y es que la intuición juega a veces malas pasadas pero créeme: está todo en tu sitio.

Esta es la mecánica del cambio de fechado:

  • Entre cada dos fechas [A,B) del fechado final se agregan todas las fechas del fechado original situadas entre las dos, incluyendo la primera A pero no la segunda B, y se asigna el resultado a A en el fechado final.
  • Si hay omitidos en alguno de los intervalos se actuará prescindiendo de ellos, como si el intervalo fuera más corto.
  • Da lo mismo que los omitidos salgan en el medio de la serie que por el principio o el final, pues las series temporales son conceptualmente infinitas.

En el caso de la media, por ejemplo, el resultado con omitidos será la suma de los no omitidos dividida por el número de valores sumados, dando un estadístico congruente si se se trata de una distribución más o menos uniforme, pero en general supondrá una distorsión más o menos importante. Por ejemplo, si se trata de la suma de valores del mismo signo el sesgo podría ser muy notable. Pero el nivel de distorsión no es algo que se pueda saber de antemano de forma automática. Si esta distorsión no es aceptable entonces es el analista el que debe tomar partido según lo que se quiera hacer con la serie y el conocimiento que se tenga sobre ella:

  • o se rellenan previamente los datos originales de una forma consistente mediante interpolaciones o previsiones más o menos razonables
  • o se sustituyen los datos distorsionados por omitidos en el agregado final, o en el original, según resulte más cómodo.

En ambos casos existen en TOL expresiones para lograrlo, aunque no se puede dar una receta universal.

En el caso que proponías se toman los días desde el 31 de un mes A hasta el día 31 del siguiente mes B que tenga 31 días, incluyendo el primero pero no el segundo, y se han de agregar para el cambio de fechado con valor en A. Así pues, todos los días anteriores a B=y2011m01d31 han de adjuntarse a A=y2010m12d31, independientemente de que la serie original tenga valor o no en A=y2010m12d31, lo cual es equivalente a tener un omitido en dicha fecha, del mismo modo que lo haría si el omitido estuviera en cualquier otra fecha intermedia.

Si el dato del y2010m12d31 no te resulta fiable o no te es útil o te molesta por cualquier motivo, simplemente puedes hacer un SubSer(...,y2011m01d31,...), bien en la serie original o bien en la agregada, pero el DatCh no es quién para hurtar ese dato, del mismo modo que no te gustaría que te lo hurtase por el medio de la serie, sólo porque hubiera un cierre el viernes santo, por poner un ejemplo.

comment:11 Changed 13 years ago by Alfredo Torre

Creo que lo has dejado muy claro. Muchas gracias!

Por si a alguien le es de utilidad, dejo aquí una función que recorta la salida de DatCh entre dos fechas del fechado destino interiores al intervalo de definición de la serie original:

//////////////////////////////////////////////////////////////////////////////
Serie DatChUsu(Serie ser, TimeSet dating, Code stat)
//////////////////////////////////////////////////////////////////////////////
{
  Serie serDC = DatCh(ser, dating, stat);
  Date ini = Succ(Succ(First(ser), C, -1), dating,  1);
  Date end = Succ(Succ(Last(ser),  C,  1), dating, -1);
  SubSer(serDC, ini, end)
};
//////////////////////////////////////////////////////////////////////////////

comment:12 Changed 13 years ago by Pedro Gea

Los estadísticos sobre series temporales ignoran la presencia de omitidos, si quieres considerarlos, la solución está en usar una función distinta, en mi opinión no hace falta modificar el funcionamiento de DatCh ni ofrecer uno alternativo.

Por ejemplo, para encontrar el valor de la primera fecha del intervalo, podemos usar:

Real BeginS(Serie serie, Date begin, Date end) {
  SerDat(serie, begin)
};

que tiene un comportamiento distinto a FirstS que devuelve el primer valor conocido del intervalo.

Así se puede obtener la serie buscada como:

Serie sr_1 = SubSer(Rand(4, 8, Daily), y2011, y2011m12d31);
Serie sr_d = DatCh(sr_1, D(31), BeginS);

comment:13 Changed 13 years ago by Alfredo Torre

Brillante, pgea.

Creo que estaría bien que existieran los estadísticos de Serie entre dos fechas que devolvieran omitidos si hay algún omitido en ese intervalo de la Serie. Sería algo así como:

Real SumS_IOO(Serie serie, Date begin, Date end)
{
  Real dist  = CountS(CalInd(C, Dating(serie)), begin, end);
  Real count = CountS(serie, begin, end);
  If(dist!=count, ?, SumS(serie, begin, end))
};

o existe otra forma más fácil o rápida de hacerlo?

comment:14 in reply to:  13 Changed 13 years ago by Víctor de Buen Remiro

Más que retorcer cada uno de los estadísticos creo que es más sencillo crear una nueva función de cambio de fechado que conserve los omitidos

//////////////////////////////////////////////////////////////////////////////
  Serie DatChUnk(Serie serie, TimeSet dating, Code stat)
//Devuelve el cambio de fechado de una serie conservando los omitidos, o sea,
//si en un intervalo la serie original tiene un omitido entonces la serie
//agregada tendrá omitido en ese intervalo. Esto ocurrirá independientemente
//de la posición del omitido en la serie original. Si el omitido resulta
//estar en el primer intervalo, la serie agregada perderá el dato inicial y
//su fecha inicial se adelantará una posición, y si está en el último se 
//retrasará la fecha final.
//////////////////////////////////////////////////////////////////////////////
{
  //Serie con el cambio de fechado obviando los omitidos
  Serie serie_dc = DatCh(serie, dating, stat);
  //Serie agregada del número de datos no omitidos
  Serie notUnk = DatCh(Not(IsUnknown(serie)), dating, SumS);
  //Serie infinita de conteo de fechas del cambio de fechado
  Serie countAll  = DatCh(CalInd(Dating(serie), Dating(serie)), dating, SumS);
  //Cuando no coinciden las dos series anteriores hay que devolver omitido
  Serie serie_dc_unk = IfSer(Eq(countAll,notUnk),serie_dc,?*serie_dc)
};

//Ejemplo de uso
Serie serie = IfSer(Pulse(y2011m06d15,Daily),?,
  SubSer(Rand(4, 8, Daily), y2011, y2011m12d31));
//Cambio de fechado obviando los omitidos
Serie serie_dc = DatCh(serie,D(31),FirstS);
//Cambio de fechado conservando los omitidos
Serie serie_dc_unk = DatChUnk(serie,D(31),FirstS);

El resultado del ejemplo daría esta tabla

D(31)serie_dcserie_dc_unk
y2010m12d315.64974195324?
y2011m01d317.475922728897.47592272889
y2011m03d314.035494740124.03549474012
y2011m05d317.24275657255?
y2011m07d315.471196181145.47119618114
y2011m08d315.015107148335.01510714833
y2011m10d316.409474049696.40947404969
y2011m12d317.53088257276?

comment:15 Changed 13 years ago by Alfredo Torre

Me parece genial. Crees que se podría incluir en el paquete de StdLib?

comment:16 Changed 13 years ago by Víctor de Buen Remiro

Sus deseos son órdenes para este equipo de desarrollo.

comment:17 Changed 13 years ago by Víctor de Buen Remiro

(In [5111]) Refs #1518
Adding new function DatChUnk that implements a dating change conserving unknown values

comment:18 Changed 13 years ago by Jorge

(In [5112]) refs #1518

comment:19 Changed 13 years ago by Víctor de Buen Remiro

Jorge acaba de subir la nueva versión del paquete StdLib.0.5 que ya contiene esta función.

Nota: para usar el nuevo paquete hay que actualizarlo con el gestor de paquetes de TolBase y arrancar una nueva sesión para que surja efecto ya que se carga al inicio y no es posible recargar un paquete en tiempo de ejecución.

comment:20 Changed 13 years ago by imendez

Gracias a todos por las aportaciones. Me alegro de que, aunque la intuición me haya jugado una mala pasada (qué razón tenías, Víctor, y cuánto me costó verlo), al final haya servido para algo.

Saludos.

comment:21 Changed 13 years ago by Alfredo Torre

Así da gusto...

Gracias!

Note: See TracTickets for help on using tickets.