IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Access Discussion :

Interpoler des valeurs pour des enregistrements vides (données manquantes) [AC-2010]


Sujet :

Access

  1. #21
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Bonjour,

    Comme le note Nico, tu as une séquences de plus de 24 valeurs manquantes (28 je crois).

    Donc ça risque d'être compliqué de reconstituer cette séquence avec des méthodes d'interpolation.

    Je crois aussi que les méthodes à base de polynômes ne seront pas non plus optimums dans ce cas.

    Il aurait été plus juste, comme ça a été dit, de chercher à déterminer les paramètres d'une fonction périodique.

    Peut-être comme dans ce document (cf. Interpolation trigonométrique).

    Cdlt,

  2. #22
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Bonjour,

    Au pire des cas, tu fais une interpolation linéaire, pour chaque valeur manquante,entre la valeur du jour précédent à la même heure, et le jour suivant à la même heure, une moyenne mobile avec comme période le jour.

  3. #23
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    ReBonjour,

    J'ai appliqué la méthode avec la fonction trigo que je t'ai donné en lien dans le document, et j'obtiens pour le jour manquant 16, une moyenne de 28,36413222..., contre 28,32291666.. avec la méthode de la moyenne que tu avais proposé dans ton 1er message.

    Cdlt,

  4. #24
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 245
    Points
    245
    Par défaut
    Bonjour User,

    Par contre l'interpolation devrait marcher s'il n'y a que de-ci de-là une valeur manquante entourée de valeurs connues... Mais bon... suis pas assez calé en math pour me pencher dessus maintenant.
    ... même si ça me semblait plus joli, je pense que je vais m'orienter vers une fonction trigonométrique (et au pire, une moyenne mobile).
    Et comme tu le dis ça donne une valeur réaliste en plus.

    Par contre User, j'ai regardé les formules de l'interpolation trigonométrique... Et j'avoue que je suis perdu dans les équations et les matrices.... Et ne vois pas du tout par quel bout prendre ça...
    Dans mon cas, vu que je n'aurai que des portions d'année (de longueur variable en fonction des analyse que j'aurai à faire), il faudra que ma période soit variable (en soit pas trop compliqué a mettre en oeuvre ça).
    Mais la résolution du calcul matriciel, je suis plus que perdu ...
    Tu as une source pour m'aider a mettre ça en oeuvre en VBA?

    Un tout grand merci User et Nico pour votre aide et réflexions!
    Je vous souhaite une belle journée.

  5. #25
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Belle journée,

    Si tu veux je peux de passer mon code.

    Cdlt,

  6. #26
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Bon, je me lance et te donne mon code avec quelques explications, mais je te précise bien que je ne suis pas un spécialise :

    Cette fonction trigo (chaque terme en sinus ou cosinus possède un coef à déterminer) elle prend en argument un indice de jour et renvoie une moyenne de températures pour ce jour.

    Cette fonction comporte 4 termes, donc 4 coef à déterminer. Pour faire une bonne interpolation, il faudra donc prendre en compte 4 paires de valeurs (x1,y1)...(x4,y4)

    ça revient à résoudre un système de 4 équations à 4 inconnue.

    x c'est les indices des jours et y pour les moyennes des températures (les indices des jours tu peux les obtenir dans une requête).

    si tu a un jour complet de valeurs manquantes, un jour ou tu n'as pas de moyenne, par exemple le jour4, retiens les valeurs pour :

    Jour1, Jour3, Jour5, Jour7 avec des intervalles réguliers de 2 jours

    et ensuite tu fais une interpolation pour jour4

    cela revient à résoudre un système de 4 équations à 4 inconnues, qui te donne les valeurs des coefficients de la fonction périodique.

    Ensuite, tu peux passer à la fonction l'indice du jour sans moyenne, et cela te donne une estimation de la température pour ce jour.

    Je te donne la base à tester..

    Tu testes la fonction InterpolationTrigo comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ? InterpolationTrigo("R_Temperatures", 16)

    J'espère ne pas me tromper car c'est assez complexe
    Fichiers attachés Fichiers attachés

  7. #27
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 245
    Points
    245
    Par défaut
    Rhoooo!!! Me suis connecté à tout hasard car j'avais une idée à vérifier et je te lis

    Un tout GRAND merci pour le code!! Je vais regarder ça demain et vendredi. Tes explications sont beaucoup plus limpides que celles du lien et je pense avoir saisi le mécanisme :-)

    A bientôt et très belle soirée à toi User

  8. #28
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 245
    Points
    245
    Par défaut
    Bonjour User,

    je suis en train de décomposer ton code. Pour un non spécialiste c'est bien dense ;-)

    Par ailleurs, le premier test que je viens de faire me renvoie un message d'erreur (erreur de compilation; projet ou bibliothèque introuvable).
    Il semble s'arrêter sur cette ligne : Par hasard, il ne faudrait pas un complément particulier ou une bibliothèque que je n'ai pas installé ?

    Belle journée à toi!

  9. #29
    Expert confirmé

    Homme Profil pro
    consultant développeur
    Inscrit en
    Mai 2005
    Messages
    2 929
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : consultant développeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 929
    Points : 4 847
    Points
    4 847
    Par défaut
    OUI, Regarde si tu as une reference manquante dans le menu VBE / Outils / références, certainement la bibiotheque "Microsof excel 1n.n object library"

    cdlt

  10. #30
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Bonjour,

    Oui, tu dois avoir la référence microsoft Excel de marquée "Manquante", il faut juste la décocher, j'avais oubliée de l'enlever

    Sinon, il faut juste regarder la fonction InterpolationTrigo et la requête R_Temperatures.

    Le reste, c'est pour résoudre le système d'équations.

    Cdlt,

  11. #31
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 245
    Points
    245
    Par défaut
    re bonjour,

    En effet la référence "Microsoft excel 16.n object library" était marquée comme manquante.

    Actuellement, la fonction renvoie la valeur moyenne quotidienne estimée pour le jour correspondant à l'indice.
    Je vais essayer de voir comment faire pour modifier ton code de manière à remplir chaque enregistrement horaire qui a une température manquante.
    En effet, je dois garder une traçabilité des modifications que j'ai apportée aux données.
    Dans le tableau T_Temperature, c'est une bonne idée d'avoir une colonne pour les nouvelles valeurs (là où c'est 0 pour l'instant) et une colonne où peut se stocker l'info qu'on a fait une modif (celle avec les case à cocher).

    Je reviens bientôt (ou demain) pour plus de nouvelles

    Cdlt

  12. #32
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 245
    Points
    245
    Par défaut
    re bonjour,

    J'ai fait un petit test.

    La requète R_Temperatures calcule les moyennes quotidiennes, si j'ai bien compris, via
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IndJour: ([IdTemperature]-1)\24+1
    Je me suis demandé ce qui se passe si on se base sur des demi-journées (12 au lieu de 24 dans l'équation ci-dessus).
    Cette requête ainsi modifiée me donne en IndJour n° 32, une valeur correspondant à la moyenne des 4 heures connues (pour le 26/07). Et en 33, une valeur manquante ce qui est normal (vu que l'on a pas de valeur pour la première demi journée du 27/07).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ?InterpolationTrigo("R_Temperatures", 33)
    donne bien une valeur pour cette demi-journée.
    Mais si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InterpolationTrigo("R_Temperatures", 32)
    , pour en recalculer la valeur extrapolée vu qu'en fait la moyenne n'est basée que sur 4 heures, il me dit que j'ai une utilisation incorrecte du null. Ceci très probablement parce que la valeur de température suivante est vide...

    Y-a-t'il un moyen pour que si c'est vide , il puisse chercher la valeur suivante non vide la plus proche, pour faire son calcul?
    Ou alors, ne faudrait-il pas faire d'abord le calcul pour trouver la valeur manquante, puis refaire le calcul pour la valeur précédent cette valeur manquante et la "manquante", histoire d'affiner l'interpolation?

    Qu'en penses-tu?

    Bon après-midi!

  13. #33
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Bonsoir,

    En résumé, on a des données dont on sait juste qu'elles suivent globalement une fonction périodique, mais vraiment globalement, donc c'est difficile de réaliser une bonne estimation des valeurs manquantes.

    Alors, je me suis demandé si mon code était correct, et j'ai donc simplement ajouté une fonction pour remplir la table avec les valeurs renvoyées par une fonction périodique quelconque :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Do Until rs.EOF
     
            rs.Edit
            rs!ValeurTemperature = 23 * Sin(i * 2 * pi / 24) + 24 * Cos(i * 2 * pi / 24)
            rs!ValeurTemperature2 = 23 * Sin(i * 2 * pi / 24) + 24 * Cos(i * 2 * pi / 24)
            rs.Update
     
            rs.MoveNext
            i = i + 1
     
    Loop
    Ici avec une période T de 24, j'utilise la fonction :

    f(i) = 23 * Sin(i * 2 * pi / T) + 24 * Cos(i * 2 * pi / T)

    Pour remplir les données avec cette fonction que tu peux modifier, il faut exécuter :

    Ensuite, j'obtiens la valeur estimée avec la fonction InterpolationTrigo à laquelle j'ai ajoutée un paramètre pour la période (ici 24), exemple d'exécution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ? InterpolationTrigo("T_Temperature", 24, 8)
    Et j'obtiens une très bonne estimation de la valeur, donc ça ne vient pas de l'algo. J'ai aussi résolu le souci que tu avais avec les valeurs nulles.

    Je te joins le fichier...
    Fichiers attachés Fichiers attachés

  14. #34
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 245
    Points
    245
    Par défaut
    Bonjour User,

    Merci pour le petit-dej que j'ai trouvé ce matin en ouvrant le forum :-)

    Pour être sûr de bien comprendre, la période, c'est l'intervalle de données sur laquelle la fonction ajuste l'équation? 24 pour 24h et 1 pour 1h?

    J'ai testé la nouvelle version de ton code. Il n'y a aucun soucis pour utiliser le code RemplireDonnees() et en effet l'estimation fonctionne ensuite. L'algo est ok :-)

    Du coup, j'ai dupliqué ta base, mis mes valeurs et testé la fonction d'interpolation point par point dans les zones de valeurs manquantes (ID 377 à 404; et en 692) (via un formulaire).

    En 692, pas de soucis. une seule valeur manquante entourée de valeurs connue. J'obtiens une estimation interpolée dont la valeur change en fonction de la période choisie. Ca me semble ok.

    Par contre, quand je cherche une valeur interpolée à partir de ID=377 jusque 385 j'ai un message d'erreur. De 385 à 404, j'ai des valeurs, au départ, aberrantes qui vers la fin de l'intervalle se rapprochent de valeurs réalistes.

    Je pense qu'on est presque bon, mais je ne vois pas pourquoi ca me renvoie ces erreurs. Ou alors, j'ai pas compris un truc dans l'utilisation de la fonction?

    Je te remercie pour tes lumières et ton travail !
    Cordialement

    Pour faciliter la discussion, je te joins ici ma base test.
    Fichiers attachés Fichiers attachés

  15. #35
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Bonjour,

    Je regarderai cela plus en détail ce week-end, et si j'ai une solution je me ferai un plaisir de te la donner

    Bon week-end,

  16. #36
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 245
    Points
    245
    Par défaut
    Merci User
    Je ferai pareil aussi

    Je pense être sur une piste intéressante qui recoupe ce que tu proposes avec Lagrange (voir ici).

    Bon weekend également !

  17. #37
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Bonsoir,

    Comme cela a été dit le souci c'est vraiment le nombre de valeurs manquantes successives qui est important, environ 28.

    Donc, plus de 24 heures.

    L'idée c'est de retenir pour chaque valeur manquantes 4 valeurs proches enregistrées à la même heure du jour :

    Par exemple, pour estimer la valeur pour l'indice 380, les valeurs retenues présentes ([P]) se répartiraient comme suit :

    ----332-------------------------- 356-------------------------- 380---------------------------404-------------------------- 428-------------------------- 452
    -----|---------------24------------|---------------24------------|---------------24------------|---------------24------------|---------------24------------|
    ----[P]--------------------------- [P] ---------------------------[M]-------------------------- [M]-------------------------- [P]----------------------------[P]


    Pour estimer la température pour 380 on va donc utiliser les valeurs de 332, 356, 428 et 452.

    Et on va appliquer l'interpolation trigo en utilisant ces valeurs.

    Mais tu peux remarquer qu'il y a un saut entre 380 et 428 de 48 heures (dû à une valeur manquante supplémentaire 404), ce qui explique une mauvaise interpolation (intervalles pas réguliers) pour 380.

    On pourrait imaginer de prendre 48 heures au lieu de 24 heures, et là ça donne des valeurs plutôt réaliste, avec cependant de petits saut de températures au début et à la fin.

    ----308--------------------------------------------- 356---------------------- 380-----------------------404----------------------------------------------- 452
    -----|------------------------48----------------------|-------------24----------|-------------24----------|-------------------------48-----------------------|
    ----[P]-----------------------------------------------[P]-----------------------[M]----------------------- [P]------------------------------------------------[P]

    Faudra-t-il procéder à des ajustements

    Bonne soirée,

    J'ignore si cette façon de procéder est correcte...je te joins les données.
    Fichiers attachés Fichiers attachés

  18. #38
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 245
    Points
    245
    Par défaut
    Bonjour User,

    Faut pas travailler comme ça le weekend ... je pourrai dire ça aussi pour moi

    Un grand merci pour tes derniers codes.
    J'ai testé, l'interpolation de Lagrange et l'interpolation trigonométrique. Dans les deux cas, le code fonctionne bien
    Au niveau des valeurs estimées, l'interpolation trigo donne des estimations qui sont assez correctes pour autant que je travaille avec des plages de valeurs manquantes. Quand il s'agit de valeurs manquantes, de-ci de-là, les estimations de températures obtenues sont un peu plus "fantaisistes" mais restent raisonnables (du genre on estime une valeur manquante à 35.78°C qui est encadrée par des valeurs de 28°C et 26°C).
    L'interpolation de Lagrange dans le même cas de figure est plus robuste et, en un même point, les valeurs estimées varient en fonction de l'étendue de la plage de valeurs manquantes adjacentes. Ce qui me semble tout a fiat logique.

    De mon côté, j'ai repris les codes de l'interpolation par spline et de la fonction de MajTemperatures() que tu avais suggéré au tout début. Dans cette fonction, j'ai introduit un second tableau (t2) qui reprends en fait tous les enregistrements qui ont des données de températures.
    Et utilisé ce tableau là pour le passer à la fonction spline. En ajoutant une petite correction pour bien lire la bonne colonne dans la fonction, ca roule impec!
    Du coup, je me suis aussi penché sur la fonction d'interpolation cubique, que j'avais vu ailleurs, l'ai adaptée pour Access et ça roule aussi :-)

    Pour résumer, je vais garder les fonctions d'interpolation de Lagrange, spline et cubique et faire un formulaire qui laissera le choix aux utilisateurs. Avec ça, il y en a pour tous les goûts je pense...

    Un tout grand merci pour ton aide et le temps passé dessus (et tout ce que j'ai appris pendant ce temps là)!!



    Au cas où ça peut servir à d'autres, voici les codes que je retiens (sans oublié les fonctions qui sont implémentées dans le module trigo du dernier fichier que tu as posté) et utilise dans mon cas de figure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
     
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Fonction qui met a jour un tableau en utilisant soit un spline, soit une interpolation cubique en fonction d'un choix utilisateur
    ' pour calculer les valeurs de températures manquantes
    ' Un grand merci à User pour son aide (voir ici : https://www.developpez.net/forums/d2089798-2/logiciels/microsoft-office/access/interpoler-valeurs-enregistrements-vides-donnees-manquantes/#post11613261)
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    Public Function MajTemperatures(nomTable As String)
        Dim db As DAO.Database
        Dim rs As DAO.Recordset, x As Double, y As Double, bk As Variant
        Dim rsFiltered As DAO.Recordset
        Dim t As Variant ' variable utilisée comme tableau à 2 dimension : 1 dimension pour les champs du recordset et une autre pour les enregistrements
        Dim t2 As Variant ' variable pour tableau à 2 dimensions: contient les lignes pour lesquelles on a la températures - utile pour cubicInterpolation
        Dim i As Long
     
        Set db = CurrentDb
        Set rs = db.OpenRecordset(nomTable, dbOpenDynaset)
        rs.MoveLast
        rs.MoveFirst
        ' on transforme le recordset en un tableau à 2 dimensions t(0..rs.Fields.Count-1,0..n-1)
        t = rs.GetRows(rs.RecordCount) ' tableau qui contient toutes les données
     
        'on filtre le recordset pour ne garder que les lignes ayant une donnée de température
        rs.Filter = "Not IsNull(TempExtrapTE)"
        Set rsFiltered = rs.OpenRecordset
        rsFiltered.MoveLast
        rsFiltered.MoveFirst
        ' on transforme le recordset en un second tableau à 2 dimensions
        t2 = rsFiltered.GetRows(rsFiltered.RecordCount) ' tableau qui contient seulement les données de temp non nulles
     
        i = 0
        rs.MoveFirst
        Do Until rs.EOF
            If IsNull(t(9, i)) Then ' si pas de valeur de température pour cet enregistrement ; 9 quand on utilise la table TempStationExtrapTE
     
                x = CDbl(rs.Fields(0)) 'on se base sur le champ ID mais on peut aussi se baser sur le champ CDbl(rs!DateFull) en le convertissant en numérique: valeur d'abscisse x
     
                'en fonction de la méthode d'interpolation retenue, on utilise soit CubicInterpolation, soit spline
                'ils calculent la température correspondant à la date : valeur d'ordonnée y
                'y = CubicInterpolation(t2, 0, 9, X)
                y = spline(t2, 0, 9, x)
     
                rs.Edit
                rs.Fields(9).Value = y ' on copie la valeur de l'interpolation dans le champ adéquat, ici TempExtrapTE
                rs.Update
            End If
            rs.MoveNext ' on passe à l'enregistrement suivant
            i = i + 1
        Loop
     
        rs.Close
        Set rs = Nothing
        rsFiltered.Close
        Set rsFiltered = Nothing
        Set db = Nothing
    MsgBox "fini"
    End Function
     
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    'Fonction trouvée ici https://www.business-spreadsheets.com/forum.asp?t=120
    'et adaptée pour access
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    Public Function spline(t As Variant, indiceX As Long, indiceY As Long, x As Double) As Double
    Dim val1 As Integer
    Dim val2 As Integer
    Dim n As Integer
    Dim i As Integer, k As Integer
    Dim p As Single, qn As Single, sig As Single, un As Single
    Dim u() As Single
    Dim yt() As Single
    Dim y As Double
    Dim klo As Integer, khi As Integer
    Dim h As Single, b As Single, a As Single
     
     
    val1 = UBound(t, 2) - 1
    val2 = UBound(t, 2)
    n = UBound(t, 2)
     
    ReDim u(val1)
    ReDim yt(val2)
     
    yt(1) = 0
    u(1) = 0
     
    For i = 2 To n - 1
        sig = (t(indiceX, i) - t(indiceX, i - 1)) / (t(indiceX, i + 1) - t(indiceX, i - 1))
        p = sig * yt(i - 1) + 2
        yt(i) = (sig - 1) / p
        u(i) = (t(indiceY, (i + 1)) - t(indiceY, i)) / (t(indiceX, (i + 1)) - t(indiceX, i)) - (t(indiceY, i) - t(indiceY, (i - 1))) / (t(indiceX, i) - t(indiceX, (i - 1)))
        u(i) = (6 * u(i) / (t(indiceX, (i + 1)) - t(indiceX, (i - 1))) - sig * u(i - 1)) / p
    Next i
     
    qn = 0
    un = 0
    yt(n) = (un - qn * u(n - 1)) / (qn * yt(n - 1) + 1)
     
    For k = n - 1 To 1 Step -1
        yt(k) = yt(k) * yt(k + 1) + u(k)
    Next k
     
    klo = 1
    khi = n
    Do
        k = khi - klo
            If t(indiceX, k) > x Then
                khi = k
            Else
                klo = k
            End If
        k = khi - klo
    Loop While k > 1
     
    h = t(indiceX, khi) - t(indiceX, klo)
    a = (t(indiceX, khi) - x) / h
    b = (x - t(indiceX, klo)) / h
    y = a * t(indiceY, klo) + b * t(indiceY, khi) + ((a ^ 3 - a) * yt(klo) + (b ^ 3 - b) * yt(khi)) * (h ^ 2) / 6
     
    spline = y
     
    End Function
     
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Code adapté pour VBA Access pour une série chronologique croissante (à modifier si valeurs chronologiques décroissantes)
    '
    ' Copyright 2014 Math for Mere Mortals
    ' CubicAndBicubicLagrangeInterpolation_v3 pour Excel
    '
    ' Returns an interpolated point using local cubic interpolation on a list of X and Y values.
    ' XValues and YValues are arrays
    ' XValues : indice du champ date ou du champ ID, dans tous les cas ils sont par ordre croissant
    ' YValues : indice du champ température
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    Public Function CubicInterpolation(t2 As Variant, XValues As Long, YValues As Long, x As Double) As Variant
    Dim MinIndex As Long
    Dim ItemCount As Long
    Dim i As Long
    Dim j As Long
    Dim Numerator As Double
    Dim Denominator As Double
    Dim SubsetX() As Double
    Dim SubsetY() As Double
    Dim a As Long
     
        ReDim SubsetX(4)
        ReDim SubsetY(4)
     
        'les valeurs de x seront toujours en colonne et croissante vu que ce sont des données chronologiques
        'on cherche la valeur qui précède ou est égal à X ; X étant l'ordonnée où l'on cherche à interpoler la température
        ItemCount = UBound(t2, 2)
        For i = 2 To ItemCount 'on parcours la colonne 0 (=x) du tableau t2 du début à la fin
          ' Is this array element less than or equal to X?
          If t2(0, i) <= x Then
            ' ok la valeur est valide
            MinIndex = i
          Else
            Exit For
          End If
        Next
     
        ' Si MinIndex est inf à 1, on le fixe à 1 pour que la fenêtre de calcul commence là
        If MinIndex < 1 Then
          MinIndex = 1
        End If
        ' Si MinIndex est supérieur au nbr d'enregistrement, on le fixe à ItemCount - 3 pour que la fenêtre de calcul se termine là, au plus
        If MinIndex > ItemCount - 3 Then
          MinIndex = ItemCount - 3
        End If
     
        ' On extrait les données qui vont encadrées les valeurs manquantes, 2 avant et 2 après, pour remplir nos tableaux de 4 valeurs
        SubsetX(1) = t2(XValues, MinIndex - 1)
        SubsetX(2) = t2(XValues, MinIndex)
        SubsetX(3) = t2(XValues, MinIndex + 1)
        SubsetX(4) = t2(XValues, MinIndex + 2)
        SubsetY(1) = t2(YValues, MinIndex - 1)
        SubsetY(2) = t2(YValues, MinIndex)
        SubsetY(3) = t2(YValues, MinIndex + 1)
        SubsetY(4) = t2(YValues, MinIndex + 2)
     
     
      ' Make sure we're free of errors before doing any real calculations.
      If Len(CubicInterpolation) = 0 Then
        ' At this point we have isolated the subset of 4 points we need for the interpolation.
        ' Now we do the actual Lagrange interpolation.
        ' Assume the result is zero.
        CubicInterpolation = 0
        ' Loop once for each point in the subset of data.
        For i = LBound(SubsetX) To UBound(SubsetX)
          ' Initialize the numerator and denominator.
          Numerator = SubsetY(i)
          Denominator = 1
          ' Loop once for each potential Lagrange coefficient.
          For j = LBound(SubsetX) To UBound(SubsetX)
            ' Skip combinations of the same index.
            If i <> j Then
              ' Calculate the numerator for this term.
              Numerator = Numerator * (x - SubsetX(j))
              ' Calculate the denominator for this term.
              ' If we didn't skip some of the combinations, this denominator would be zero, which would be a bad thing!
              Denominator = Denominator * (SubsetX(i) - SubsetX(j))
            End If
          Next
          ' Include this term in the final result.
          CubicInterpolation = CubicInterpolation + Numerator / Denominator
        Next
      End If
    End Function
     
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    ' fonction qui met a jour un tableau en utilisant une interpolation de Lagrange, troisième choix pour l'utilisateur
    ' pour interpoler les valeurs manquantes de températures
    ' Un grand merci à User pour son aide (voir ici : https://www.developpez.net/forums/d2089798-2/logiciels/microsoft-office/access/interpoler-valeurs-enregistrements-vides-donnees-manquantes/#post11613261)
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    Public Function MajTemperatures_Lagrange(source As String) As Boolean
         Dim db As DAO.Database
        Dim rs As DAO.Recordset, x As Double, y As Double
        Dim t As Variant ' variable utilisée comme tableau à 2 dimension : 1 dimension pour les champs du recordset et une autre pour les enregistrements
        Dim i As Long
        Dim tabCoef As Variant
        Dim tabRes() As ExprArithm ' tableaux des coefficients de la matrice et des résultats
        Dim tabXY As Variant
        Dim tabSol As Variant ' tableau des solutions X du système d'équation.
        Dim nbrLignes As Long
        Dim indLigne As Long, indColonne As Long, indPosition As Long ' indice de ligne et de colonne
        Dim indTemperature As Long, indTab As Long
        Dim p As Long ' periode de 24 ou 48 heures
     
        p = 24 * 2
     
        Set db = CurrentDb
     
        ' on filtre 3 jours avant et 10 jours après, exemple : 13-19
        Set rs = db.OpenRecordset("select ID, TempExtrapTE from " & source & " order by ID;", dbOpenDynaset)
        rs.MoveLast
        rs.MoveFirst
     
        nbrLignes = rs.RecordCount ' nombre de lignes ici 6
     
        t = rs.GetRows(rs.RecordCount)  ' on transforme le recordset en un tableau à 2 dimension t(0..rs.Fields.Count-1,0..n-1)
     
        ReDim tabXY(0 To 1, 0 To 3) As Double
     
        For indTab = 0 To nbrLignes - 1
            If IsNull(t(1, indTab)) Then
                indTemperature = t(0, indTab)
                indPosition = indTab - 24
                i = 1
     
                ' Copie des valeurs dans le tableau correspondant : contenant les moyennes des températures
                Do Until (i > 2) ' on parcours les jours par période de 2 jours : on chevauche le jour 16 manquant pour par la suite interpoler en 16
                    If Not IsNull(t(1, indPosition)) Then
                        i = i + 1
                    End If
                    indPosition = indPosition - p
                Loop
                i = 0
                Do Until (i > 3) ' on parcours les jours par période de 2 jours : on chevauche le jour 16 manquant pour par la suite interpoler en 16
                    If Not IsNull(t(1, indPosition)) Then
                        tabXY(0, i) = t(0, indPosition) ' valeur d'indice de la demi-journée
                        tabXY(1, i) = t(1, indPosition) ' valeur moyenne
                        i = i + 1
                    End If
                    indPosition = indPosition + p
                Loop
                x = indTemperature ' on copie l'indice du jour paramètres de la fonction
                ' on évalue la fonction avec x
                y = InterpolationLagrange(tabXY, 0, 1, x)
     
                rs.FindFirst "ID=" & indTemperature
                rs.Edit
                rs!TempExtrapTE = y
                rs.Update
            End If
        Next indTab
     
        MajTemperatures_Lagrange = True
     
        rs.Close
        Set rs = Nothing
        Set db = Nothing
    End Function
     
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    ' fonction qui calcule l'interpolation de Lagrange et est appelé par la focntion précédente
    ' pour les valeurs manquantes de températures
    ' Un grand merci à User pour son aide (voir ici : https://www.developpez.net/forums/d2089798-2/logiciels/microsoft-office/access/interpoler-valeurs-enregistrements-vides-donnees-manquantes/#post11613261)
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    Public Function InterpolationLagrange(t As Variant, indiceX As Long, indiceY As Long, x As Double) As Double
        ' indiceX : indice du champ date
        ' indiceY : indice du champ température
        Dim p As Double, u As Double
        Dim i As Long, j As Long, n As Long
     
        ' formule = p1*y1 + p2*y2 +...+ pn*yn + ..
        n = UBound(t, 2) ' nombre d'enregistrements
     
        ' formule devient = p0*t(indiceY,0) + p1**t(indiceY,1) +...+ p(n-1)*t(indiceY,n)
        InterpolationLagrange = 0
     
        For i = 0 To n  ' on parcourt les lignes du tableau
            p = 1
            If Not IsNull(t(indiceY, i)) Then ' si la valeur de température n'est pas nulle alors on la prend en compte dans le calcul d'intepolation
                For j = 0 To n   ' on parcourt les lignes du tableau pour calculer le coefficient
                    If j <> i And Not IsNull(t(indiceY, j)) Then
                        p = p * (x - t(indiceX, j)) / (t(indiceX, i) - t(indiceX, j))
                    End If
                Next j
                InterpolationLagrange = InterpolationLagrange + (p * t(indiceY, i)) ' on ajoute à la formule (p * t(indiceY, i))
            End If
        Next i
     
    End Function
    Une petite vérification de la qualité des interpolations, montre que sur des plages de données manquantes, Lagrange donne une valeur avec le plus petit écart par rapport à la valeur réelle.
    Nom : ecart.png
Affichages : 410
Taille : 16,1 Ko

  19. #39
    Rédacteur/Modérateur

    Avatar de User
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    8 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 8 412
    Points : 19 988
    Points
    19 988
    Billets dans le blog
    66
    Par défaut
    Merci pour ton retour

    La cubic interpolation semble se baser sur l'interpolation de lagrange, mais je pense que ça dépend avant tout du choix de tes points sur l"axe x, de façon à ce que l'intervalle entre les points soit le même.

    Bonne semaine

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 25
    Dernier message: 20/11/2013, 14h43
  2. Élimination des enregistrements vides
    Par goldray dans le forum Forms
    Réponses: 2
    Dernier message: 31/12/2012, 18h26
  3. Exclure des enregistrements vide dans une requête sql
    Par beegees dans le forum Langage SQL
    Réponses: 1
    Dernier message: 31/03/2009, 19h42
  4. Réponses: 4
    Dernier message: 06/11/2007, 23h31
  5. requete devant ramener des enregistrements vides
    Par CrazyCat dans le forum Requêtes
    Réponses: 3
    Dernier message: 22/06/2006, 17h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo