Remplacement des données manquantes par des valeurs régressées<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />Salut
J'ai une série chronologique pour laquelle la variable a des valeurs manquantes. Je voudrais remplacer les valeurs manquantes par un modèle linéaire dérivé des valeurs disponibles les plus proches dans le temps.
Quelle serait la meilleure façon ?
Et si le script pouvait faire ça sur toutes les colonnes de ma table (sauf l'heure), ce serait encore mieux
Merci
Exemple
Ce que j'ai
| t | Sortir |
|---|
| 0 | dix |
| 1 | . |
| 2 | . |
| 4 | 30 |
| dix | . |
| 20 | dix |
Ce que je veux:
| t | Sortir |
|---|
| 0 | dix |
| 1 | 15 |
| 2 | 20 |
| 4 | 30 |
| dix | 22,5 |
| 20 | dix |
Re : Remplacement des données manquantes par des valeurs régresséesLa façon dont les formules JMP fonctionnent, ainsi que les fonctions JMP, est que la dernière variable créée ou référencée est ce qui est transmis par la formule ou la fonction. Par conséquent, dans votre formule de remplacement, ce qui est renvoyé comme valeur de lignes est la valeur de la matrice « Valeurs » égale au nombre Row(). Et comme la matrice "Valeurs" est l'endroit où les valeurs des colonnes ont été obtenues avec le message << get valeurs, et que les interpolations ont été faites sur la matrice "Valeurs", en spécifiant
valeurs[Ligne()]
la formule déplace les valeurs une ligne à la fois dans la nouvelle colonne.
Une autre façon d'expliquer cela est de passer par le flux de processus de la formule
Toutes les formules parcourent toutes les lignes d'une table de données, de la ligne 1 à la dernière ligne de la table de données.
Lors du traitement de la ligne 1, toutes les valeurs de la colonne « p (g/L) » sont déplacées dans une matrice pour traitement. Traitement des boucles depuis l'élément 1 de la matrice jusqu'à la fin de la matrice, en effectuant des interpolations si nécessaire. A la fin du bouclage, tous les éléments de la matrice sont renseignés. Ensuite, la valeur du premier élément de la matrice « Valeurs » est renvoyée à la formule en tant que valeur à utiliser pour la 1ère ligne de la colonne.
Ensuite, la valeur de la ligne est déplacée pour exécuter la formule pour la 2ème ligne, et les seules instructions exécutées pour la 2ème ligne sont
valeurs[Ligne()]
qui renvoie à la formule la valeur de la ligne des colonnes 2, qui est l'élément 2 de la matrice "Valeurs".
La formule continue de boucler une fois pour chaque ligne suivante, en exécutant uniquement l'instruction
valeurs{Ligne()]
J'espère que cela a du sensRe : Remplacement des données manquantes par des valeurs régresséesJim,
Merci beaucoup. cela fonctionne très bien maintenant. pouvez-vous m'expliquer ce que sont les dernières "values[Row()];" fait
Re : Remplacement des données manquantes par des valeurs régresséesSi vous souhaitez que la valeur de la colonne Interprétée soit égale à 0 chaque fois que la valeur :Time est 0, une modification du code comme ci-dessous fonctionnerait
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 : Remplacement des données manquantes par des valeurs régresséescela le fait pour la première valeur, mais ce dont j'ai besoin, c'est que tout "Time" est 0, la valeur interpolée est zéro. la colonne de temps aura plusieurs 0
Re : Remplacement des données manquantes par des valeurs régresséesD'après le code que je vous ai fourni, est-ce ce que vous demandez ?
If( Is Missing( values[1] ),
values[1] = 0
);Re : Remplacement des données manquantes par des valeurs régresséesJim,
J'ai fait fonctionner le script. J'ai dû ajouter quelques calculs afin de tenir compte du temps delta pour le calcul d'augmentation et la boucle d'évaluation de l'interpolation. Le dernier problème est que puisque je prévois de joindre plusieurs fichiers d'exécution et d'exécuter le script, j'aurai plusieurs endroits où temps = 0 (temps : 0,12,24,48,0,12,24,48... ), ainsi la première valeur interpolée doit être 0 pour le bloc de données donné. Je ne sais pas comment faire cela avec la notation matricielle.
Re : Remplacement des données manquantes par des valeurs régresséesD'après mes expériences, j'ai eu trop de problèmes en essayant de référencer la colonne de formule réelle dans la formule. Ainsi, l'approche présentée. J'étais également préoccupé par votre formule du point de vue du nombre de fois que vous parcourez les données avec votre boucle For(). Ma méthode parcourt la table de données une seule fois... sans compter le remplacement de l'itération.Re : Remplacement des données manquantes par des valeurs régresséesJim,
Merci beaucoup, je vais essayer. Je suis curieux cependant ; en revenant au script original, je pensais que l'erreur récursive provenait de la ligne 3, à cause de cela, il faudrait calculer l'incr et obtenir rows-counter-1 = 3-2-1 = 0. j'ignorerais le message d'erreur et il interpole avec succès le reste de la colonne, à l'exception de la toute fin.l'ajout de données supplémentaires au tableau à interpoler fait descendre le problème. je pensais qu'il s'agissait peut-être de problèmes distincts.
Re : Remplacement des données manquantes par des valeurs régresséesVous rencontrez un problème récursif dans la formule lorsque vous essayez de modifier les valeurs dans la colonne de formule elle-même.J'ai retravaillé votre formule pour effectuer tout le travail en amont à l'aide d'une matrice.Les valeurs résultantes sont ensuite utilisées pour les valeurs de chaque ligne
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 : Remplacement des données manquantes par des valeurs régresséesvoici le tableau
Re : Remplacement des données manquantes par des valeurs régresséesJim,
Merci d'avoir clarifié. J'ai un problème avec le script. il n'exécutera pas et n'interpolera pas le dernier intervalle.je ne peux pas dire si cela a quelque chose à voir avec l'imbrication des boucles ou les conditions « while ». fondamentalement, quelle que soit la longueur de la table, il ne peut pas remplir le dernier intervalle de données manquantes.
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 : Remplacement des données manquantes par des valeurs régresséesJMP n'est pas spécifique à la casse dans les fonctions et les instructions, donc rows=RowsRe : Remplacement des données manquantes par des valeurs régresséesJim,
y a-t-il une différence entre « lignes » et « lignes » ? pourriez-vous s'il vous plaît l'expliquer. Je suis un noob.
Re : Remplacement des données manquantes par des valeurs régresséesBonne prise... ça devrait être
If this is row 1 initialize a variable named counter to 0
Re : Remplacement des données manquantes par des valeurs régresséesmerci ça a marché !tu as commenté
If this is row 1 initialize a variable named counter to 1
, tu voulais dire "compteur à 0" ?
Re : Remplacement des données manquantes par des valeurs régresséesVoici une version mise à jour/annotée de mon code original.Tout ce que vous devez faire est de changer le nom de la colonne de "Sortie" en quel que soit le nom de la colonne dont vous souhaitez modifier les valeurs.
// 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 : Remplacement des données manquantes par des valeurs régresséesTxnelson,
pourriez-vous mettre à jour le script avec des commentaires ? Je suis nouveau sur JSL et j'ai besoin d'aide pour comprendre comment cela s'applique à mon problème. J'ai le même besoin qu'OP mais je n'ai qu'une seule colonne à remplir.Alternativement, j'ai utilisé le code VBA suivant dans le passé pour remplir les données manquantes dans Excel. Je me demandais s'il y avait quelque chose de similaire à la fonction End(xlDown).value dans JSL. le décalage est utilisé pour spécifier où se trouvent les données de point temporel. Merci!
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 : Remplacement des données manquantes par des valeurs régresséesSpot sur MS,
Acclamations!
Re : Remplacement des données manquantes par des valeurs régresséesJ'ai eu un problème similaire il y a quelques années et j'ai écrit un script pour effectuer une imputation par « régression locale ».
Voici une version mise à jour :
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 : Remplacement des données manquantes par des valeurs régresséesvoici un script qui fera la tâche
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 : Remplacement des données manquantes par des valeurs régresséesMerci Ron mais je ne vois rien là-dedans qui fasse de l'interpolation ?
Re : Remplacement des données manquantes par des valeurs régresséesessayez ceci pour commencer
Complément d'imputation