Reemplazo de datos faltantes por valores retrocedidos<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />Hola
Tengo una serie de tiempo para la cual a la variable le faltan valores. Me gustaría reemplazar los valores faltantes por un modelo lineal derivado de los valores disponibles más cercanos en el tiempo.
Cúal seria la mejor manera?
Y si el script pudiera hacer eso con todas las columnas de mi tabla (excepto la hora), sería aún mejor.
Gracias
Ejemplo
Lo que tengo
| t | Producción |
|---|
| 0 | 10 |
| 1 | . |
| 2 | . |
| 4 | 30 |
| 10 | . |
| 20 | 10 |
Lo que quiero:
| t | Producción |
|---|
| 0 | 10 |
| 1 | 15 |
| 2 | 20 |
| 4 | 30 |
| 10 | 22,5 |
| 20 | 10 |
Re: Reemplazar datos faltantes por valores retrocedidosLa forma en que funcionan las fórmulas JMP, junto con las funciones JMP, es que la última variable creada o a la que se hace referencia es lo que se pasa desde la fórmula o función. Por lo tanto, en su fórmula de reemplazo, lo que se devuelve como valor de las filas es el valor de la matriz "Valores" igual al número de Fila(). Y dado que la matriz "Valores" es donde se obtuvieron los valores de las columnas con el mensaje << obtener valores, y las interpolaciones se realizaron en la matriz "Valores", especificando
valores[Fila()]
la fórmula mueve los valores una fila a la vez a la nueva columna.
Otra forma de explicar esto es seguir el flujo de proceso de la fórmula.
Todas las fórmulas recorren todas las filas de una tabla de datos desde la fila 1 hasta la última fila de la tabla de datos.
En el procesamiento de la fila 1, todos los valores de la columna "p (g/L)" se mueven a una matriz para su procesamiento. Procesando bucles desde el elemento 1 de la matriz, hasta el final de la matriz, realizando interpolaciones cuando sea necesario. Al final del bucle, todos los elementos de la matriz están completos. Luego, el valor del primer elemento de la matriz "Valores" se devuelve a la fórmula como el valor que se utilizará para la primera fila de la columna.
Luego, el valor de la fila se mueve para ejecutar la fórmula para la segunda fila, y las únicas declaraciones ejecutadas para la segunda fila son
valores[Fila()]
que devuelve a la fórmula el valor de la fila de las columnas 2, que es el elemento 2 de la matriz "Valores".
La fórmula continúa repitiéndose una vez para cada fila posterior, ejecutando solo la declaración
valores {Fila()]
Espero que esto tenga sentidoRe: Reemplazar datos faltantes por valores retrocedidosJim,
Muchas gracias. esto funciona muy bien ahora. ¿Puedes explicarme cuáles son los últimos "valores [fila()];" hace
Re: Reemplazar datos faltantes por valores retrocedidosSi desea que el valor en la columna Interpretada sea igual a 0 siempre que el valor de :Time sea 0, un cambio en el código similar a lo siguiente funcionaría
For( i = 1, i <= N Rows( values ), i++,
If( :Time[i] == 0, values[i]=0); // **************
If( Is Missing( values[i] ),
counter++,
If( counter > 0,
For( k = 1, k <= counter, k++,
base = values[i - counter - 1];
incr = Abs( (base - values[i]) / (counter + 1) );
If( base < values[i],
values[(i - counter - 1) + k] = base + k * incr,
values[(i - counter - 1) + k] = base - k * incr
);
);
counter = 0;
)
)
);Re: Reemplazar datos faltantes por valores retrocedidoseso lo hace para el primer valor, pero lo que necesito es que todo el "Tiempo" sea 0, el valor interpolado es cero. la columna de tiempo tendrá varios 0
Re: Reemplazar datos faltantes por valores retrocedidosSegún el código que te proporcioné, ¿es esto lo que preguntas?
If( Is Missing( values[1] ),
values[1] = 0
);Re: Reemplazar datos faltantes por valores retrocedidosJim,
Conseguí que el guión funcionara. Tuve que agregar algunos cálculos para tener en cuenta el tiempo delta tanto para el cálculo incr como para el ciclo de evaluación de interpolación. El problema final es que, dado que planeo unir varios archivos de ejecución y ejecutar el script, tendré varios puntos donde tiempo = 0 (tiempo: 0,12,24,48,0,12,24,48... ), por lo tanto, el primer valor interpolado debe ser 0 para el fragmento de datos dado. No estoy seguro de cómo hacer esto con la notación matricial.
Re: Reemplazar datos faltantes por valores retrocedidosSegún mi experiencia, he tenido demasiados problemas al intentar hacer referencia a la columna de fórmula real dentro de la fórmula. Así, el enfoque mostrado. También me preocupaba su fórmula desde el punto de vista de la cantidad de veces que ejecuta los datos con su bucle For(). Mi método recorre la tabla de datos solo una vez... sin contar el reemplazo de la iteración.Re: Reemplazar datos faltantes por valores retrocedidosJim,
Muchas gracias, lo intentaré. Aunque tengo curiosidad; Volviendo al script original, pensé que el error recursivo provenía de la fila 3, por eso iría a calcular incr y obtendría filas-contador-1 = 3-2-1 = 0. Ignoraría el mensaje de error e interpola con éxito el resto de la columna, excepto el final.agregar más datos a la tabla que se va a interpolar reduce el problema. Pensé que podrían ser temas separados.
Re: Reemplazar datos faltantes por valores retrocedidosSe encuentra con un problema recursivo en la fórmula cuando intenta cambiar los valores dentro de la columna de la fórmula.He modificado tu fórmula para hacer todo el trabajo por adelantado usando una matriz.Los valores resultantes luego se utilizan para los valores de cada fila.
Names Default To Here( 1 );
col_name_list = Current Data Table() << get column names( string );
If( !Contains( col_name_list, "Interpolated p (g/L)" ),
Current Data Table() << New Column( "Interpolated p (g/L)",
Numeric,
Continuous,
Formula(
dt = Current Data Table();
If( Row() == 1,
counter = 0;
values = dt:Name( "p (g/L)" ) << get values;
If( Is Missing( values[1] ),
values[1] = 0
);
counter = 0;
For( i = 1, i <= N Rows( values ), i++,
If( Is Missing( values[i] ),
counter++,
If( counter > 0,
For( k = 1, k <= counter, k++,
base = values[i - counter - 1];
incr = Abs( (base - values[i]) / (counter + 1) );
If( base < values[i],
values[(i - counter - 1) + k] = base + k * incr,
values[(i - counter - 1) + k] = base - k * incr
);
);
counter = 0;
)
)
);
);
values[Row()];
)
)
);Re: Reemplazar datos faltantes por valores retrocedidosaqui esta la mesa
Re: Reemplazar datos faltantes por valores retrocedidosJim,
Gracias por la aclaración. Tengo un problema con el guión. No ejecutará ni interpolará el último intervalo.No puedo decir si tiene algo que ver con el anidamiento de los bucles o las condiciones "mientras". Básicamente, independientemente de la longitud de la tabla, no se puede completar el último intervalo de datos faltantes.
col_name_list = Current Data Table() << get column names( string );
If( !Contains( col_name_list, "Interpolated p (g/L)" ),
Current Data Table() << New Column(
"Interpolated p (g/L)",
Numeric,
Continuous,
Formula(
If(
Is Missing( :Name( "time (h)" ) ),
Empty(),
:name( "time (h)" ) == 0,
0,
!Is Missing( :Name( "p (g/L)" ) ),
:name( "p (g/L)" ),
dt = Current Data Table();
For( rows = 1, rows <= (N Rows( dt )), rows++,
If( Rows == 1, counter = 0 );
If( Is Missing( dt:name( "Interpolated p (g/L)" )[rows] ) == 1,
counter++);
If( counter > 0 & Is Missing( dt:name( "Interpolated p (g/L)" )[rows] ) == 0,
incr = (dt:name( "Interpolated p (g/L)" )[Rows] - dt:name( "Interpolated p (g/L)" )[Rows - counter - 1]) / (dt
:name( "time (h)" )[Rows] - dt:name( "time (h)" )[Rows - counter - 1]);
For( i = rows - counter, i <= rows - 1, i++,
dt:name( "Interpolated p (g/L)" )[i] = dt:name( "Interpolated p (g/L)" )[i - 1] + (incr * (dt:name( "time (h)" )[i]
-dt:name( "time (h)" )[i - 1]))
);
counter = 0;
);
);
)
)
)
);
Re: Reemplazar datos faltantes por valores retrocedidosJMP no es específico entre mayúsculas y minúsculas en funciones y declaraciones, por lo que filas = FilasRe: Reemplazar datos faltantes por valores retrocedidosJim,
¿Existe alguna diferencia entre "filas" y "Filas"? ¿Podrías explicarlo? Soy un novato.
Re: Reemplazar datos faltantes por valores retrocedidosBuen partido... debería serlo.
If this is row 1 initialize a variable named counter to 0
Re: Reemplazar datos faltantes por valores retrocedidosgracias funciono!tu comentaste
If this is row 1 initialize a variable named counter to 1
, ¿quisiste decir "contador hasta 0"?
Re: Reemplazar datos faltantes por valores retrocedidosAquí hay una versión actualizada/anotada de mi código original.Todo lo que debe hacer es cambiar el nombre de la columna de "Salida" al nombre de la columna al que desea cambiar los valores.
// Set all default referenced memory variables to this unique application
Names Default To Here( 1 );
// Set the variable dt to be a pointer to the current active data table
dt = Current Data Table();
// Loop through the data table from row 1 to the last row and use a
// variable names "rows" as the index
For( rows = 1, rows <= N Rows( dt ), rows++,
// If this is row 1 initialize a variable named counter to 1
If( Rows == 1, counter = 0 );
// If the current row's value for the column named "Output" in the
// data table referenced by "dt" is missing (blank, null) increase
// the counter
If( Is Missing( dt:output[rows] ) == 1,
counter++
);
// If row is found with a non missing value for the column called Output,
// and the counter is > 0, which indicates previous rows with missing
// values, then calculate the required values and place them in their
// appropriate rows
If( counter > 0 & Is Missing( dt:output[rows] ) == 0,
// Calculate the incremental steps to use for the missing cells
incr = (dt:output[Rows] - dt:output[Rows - counter - 1]) / (counter + 1);
// Loop across the rows with missing values and fill in the data
For( i = Rows - counter, i <= Rows - 1, i++,
dt:output[i] = dt:output[i - 1] + incr
);
// reinitialize the counter
counter = 0;
);
);Re: Reemplazar datos faltantes por valores retrocedidostxnelson,
¿Podrías actualizar el script con comentarios? Soy nuevo en JSL y necesito ayuda para entender cómo se aplica a mi problema. Tengo la misma necesidad que OP pero solo tengo una columna que debo completar.Alternativamente, he usado el siguiente código VBA en el pasado para completar los datos faltantes en Excel. Me preguntaba si hay algo similar a la función End(xlDown).value en JSL. el desplazamiento se utiliza para especificar dónde están los datos del punto de tiempo. ¡Gracias!
Sub interpolatedata()
For Each cell In Range("k4:k29")
If cell.Value = "" Then
y2 = cell.End(xlDown).Value
x2 = cell.End(xlDown).Offset(0, -8).Value
y1 = cell.End(xlUp).Value
x1 = cell.End(xlUp).Offset(0, -8).Value
x = cell.Offset(0, -8).Value
y = (y1) + (x - x1) * (y2 - y1) / (x2 - x1)
cell.Value = y
End If
Next
Re: Reemplazar datos faltantes por valores retrocedidosSpot en EM,
¡Salud!
Re: Reemplazar datos faltantes por valores retrocedidosTuve un problema similar hace algunos años y escribí un guión para realizar la imputación mediante "regresión local".
Aquí hay una versión actualizada:
dt = Current Data Table();
n = N Rows(dt);
x = Column(1);// Column("t")
For(i = 2, i <= N Col(dt), i++,
y = Column(i);
For Each Row(
If(1 < Row() < n & Is Missing(y[]),
// find previous non-missing row
Eval(Eval Expr(r1 = Max(dt << get rows where(!Is Missing(y[]) & Row() < Expr(Row())))));
// find next non-missing row
Eval(Eval Expr(r2 = Min(dt << get rows where(!Is Missing(y[]) & Row() > Expr(Row())))));
y[] = y[r1] + (y[r2] - y[r1]) / (x[r2] - x[r1]) * (x[] - x[r1]);
)
)
);
Re: Reemplazar datos faltantes por valores retrocedidosaquí hay un script que hará la tarea
Names Default To Here( 1 );
dt = Current Data Table();
For( rows = 1, rows <= N Rows( dt ), rows++,
If( Rows == 1, counter = 0 );
If( Is Missing( dt:output[rows] ) == 1,
counter = counter + 1,
If( counter > 0,
incr = (dt:output[Rows] - dt:output[Rows - counter - 1]) / (counter + 1);
For( i = Rows - counter, i <= Rows - 1, i++,
dt:output = dt:output[i - 1] + incr
);
counter = 0;
)
);
);
// Set all default referenced memory variables to this unique application
Names Default To Here( 1 );
// Set the variable dt to be a pointer to the current active data table
dt = Current Data Table();
// Loop through the data table from row 1 to the last row and use a
// variable names "rows" as the index
For( rows = 1, rows <= N Rows( dt ), rows++,
// If this is row 1 initialize a variable named counter to 1
If( Rows == 1, counter = 0 );
// If the current row's value for the column named "Output" in the
// data table referenced by "dt" is missing (blank, null) increase
// the counter
If( Is Missing( dt:output[rows] ) == 1,
counter++
);
// If row is found with a non missing value for the column called Output,
// and the counter is > 0, which indicates previous rows with missing
// values, then calculate the required values and place them in their
// appropriate rows
If( counter > 0 & Is Missing( dt:output[rows] ) == 0,
// Calculate the incremental steps to use for the missing cells
incr = (dt:output[Rows] - dt:output[Rows - counter - 1]) / (counter + 1);
// Loop across the rows with missing values and fill in the data
For( i = Rows - counter, i <= Rows - 1, i++,
dt:output[i] = dt:output[i - 1] + incr
);
// reinitialize the counter
counter = 0;
);
);Re: Reemplazar datos faltantes por valores retrocedidosGracias Ron, pero no veo nada en esto que haga interpolación.
Re: Reemplazar datos faltantes por valores retrocedidosprueba esto para empezar
Complemento de imputación