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

Calcul scientifique Python Discussion :

array avec nommage des colonnes


Sujet :

Calcul scientifique Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut array avec nommage des colonnes
    Bonjour à tous

    J'ai besoin d'une structure d'array mais :
    - qui offre aussi la possibilité de nommer les colonnes avec une extraction et une assignation à la manière d'un dictionnaire
    - qui conserve la structure d'array (l'extraction standard, les opéreations arithmétiques que l'on peut faire dessus, etc ...)


    Il y a bien la piste des arrays structurés comme là
    https://docs.scipy.org/doc/numpy-1.1...asics.rec.html
    ce qui donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A=np.array([(3.0,2.5)],dtype=[('C1',np.float),('C2',np.float)])
    A['C1']  ### Affiche 3.0
    A[0] ### Affiche (3.0,2.5)   :(
    Sauf que là, je n'ai bien sûr pas le format voulu (comme un array pur):
    A[0] donne (3.0,2.5) et non pas 3.0 comme je le voudrais.
    Pire encore, je ne peux plus faire d'opérations, comme par exemple 0.5*A ...

    J'ai essayé ensuite veinement de créer une classe dérivée de np.ndarray, mais là je m'enfonce dans les abysses de numpy et je n'y comprends pas grand chose... Je me tourne donc vers la communauté pour obtenir un peu d'aide.

    Je résumé donc mon besoin (histoire d'être clair) : disposer d'une classe qui me permette d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    A=MaClasse( [3.0,2.5] , names=["C1","C2"] )
    A[0] ## Affiche 3.0
    A[:1] ## Affiche 3.0
    A["C1"] ## Affiche 3.0
    B=A
    B["C1"]=5.0
    B[1]=7.0  ## B contient donc les valeurs : [5.0, 7.0]
    A+B
    0.5*A
    A*B
    Merci à vous

    Lg_53

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 752
    Par défaut
    Salut,

    En écrivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    A=np.array([(3.0,2.5)],dtype=[('C1',np.float),('C2',np.float)])
    vous fabriquez un tableau ayant une seule ligne et 2 colonnes nommées C1 et C2.
    Normal que: A['C1'] n'affiche qu'une valeur alors que A[0] affiche la ligne.
    Avec deux lignes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> A=np.array([(3.0,2.5),(1,2)],dtype=[('C1',np.
    >>>
    >>> A
    array([(3.0, 2.5), (1.0, 2.0)],
          dtype=[('C1', '<f8'), ('C2', '<f8')])
    >>> A['C1']
    array([ 3.,  1.])
    Comme avec ce genre de tableau, seules les colonnes sont d'un type homogène, vous allez pouvoir faire des opérations par colonnes mais pas sur l'ensemble du tableau.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre émérite

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 662
    Par défaut
    Salut,

    Peut-être déjà envisagé, mais vu qu'il n'est pas mentionné dans le post, et Pandas? Avec pandas on peut gérer les données sous la forme d'un dictionnaire (récupérer une colonne par une clé par exemple), mais aussi faire des calculs sur les lignes ou les colonnes, et même tout le tableau à la fois.

    J

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 752
    Par défaut
    Citation Envoyé par Julien N Voir le message
    Peut-être déjà envisagé, mais vu qu'il n'est pas mentionné dans le post, et Pandas? Avec pandas on peut gérer les données sous la forme d'un dictionnaire (récupérer une colonne par une clé par exemple), mais aussi faire des calculs sur les lignes ou les colonnes, et même tout le tableau à la fois.
    Sûr que pandas est un peu plus souple pour gérer les tableaux de n'importe quoi... mais il y a encore plus de documentations (et d'exemples) à lire que pour numpy...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Salut,

    Merci pour vos réponses rapides.

    @wiztricks: Ah oui, je comprends. Bien dommage alors du coup que je ne puisse faire des opérations que sur les colonnes et pas sur tout le tableau entier. Car c'est juste ce qui manque pour répondre à mon beosin.

    @Julien: Oui panda, j'avais regardé un peu, mais j'en ai pas parlé. Mon souci c'est que grosso modo je vais avoir besoin un grand nombre de fois de caster vers ou depuis un numpy.ndarray (pour que ca puisse communiquer avec scipy.ode). Déjà que les séries pandas, c'est très couteux à manipuler (100 fois plus lent qu'un array selon cette source --> https://penandpants.com/2014/09/05/p...-numpy-arrays/ ), alors si en plus je dois faire des casts réguliers ...

    On a rien sans rien me direz vous. On ne peut pas gagner en fonctionalité sans perdre un peu de performance. Ceci dit je n'ai pas besoin de toute l'artillerie panda. Juste besoin de nommer mes colonnes (dans des array 1D et 2D) et de pouvoir y accéder via ses labels. J'ai aussi exploré plus en détail la piste de créer une classe dérivée de numpy.ndarray. Finalement ca me garderait une structure en numpy.ndarray, donc ca m'évite tous des cast et ca me permet de pas trop entacher les performances. Ca serait un juste milieu.

    Je vous présente ce que j'ai pour l'instant (ca marche bien en 1D, mais j'ai encore des mises au point à faire pour le 2D):

    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
     
    from collections import OrderedDict, Iterable
    import numpy as np
     
    import pdb
    import sys
     
     
    ###Inspire de : https://docs.scipy.org/doc/numpy/user/basics.subclassing.html
    class NamedArray(np.ndarray):
     
        def __new__(cls, input_array, names=None):
            obj = np.asarray(input_array).view(cls)
            obj.colnames = OrderedDict(  (name,i) for i,name in enumerate(names) )
            return obj
     
        def __array_finalize__(self, obj):
            if obj is None: return
            self.colnames = getattr(obj, 'colnames', None )
     
        def __repr__(self):
            s=super().__repr__()
            return s[:-1]+", names="+str(self.names)+")"
     
        def __str__(self):
            return ' '.join(self.names)+'\n'+super().__str__()
     
        def Get(self,colname):
            if self.ndim == 1 :
                return self[ self.colnames[colname] ]
            else:
                return np.array(self[ :, self.colnames[colname] ])
     
        def __getitem__(self,idx):
            if isinstance(idx,str): 
                return self.Get(idx)
            else :          
                if isinstance(idx,slice):
                    return NamedArray( super().__getitem__(idx), self.names[idx] )
                else :
                    return super().__getitem__(idx)
     
        def Set(self,colname,val):
            #### Pour le 1D, a voir pour le 2D
            self[ self.colnames[colname] ] = val
     
        def __setitem__(self,idx,val):
            if isinstance(idx,str): 
                self.Set(idx,val)
            else :
                super().__setitem__(idx,val)
     
        @property
        def names(self):
            return list(self.colnames.keys())
     
     
    arr = np.arange(5)
    obj = NamedArray(arr, names=['c0','c1','c2','c3','c4'])
    print(type(obj))
    print(obj.names)
    print(obj)        ### call __str__
    print(repr(obj))  ### call __repr__
    print(obj[1])     ### call __getitem__
    print(obj['c1'])  ### call __getitem__
    print(0.5*obj)
    print(obj+obj)
    obj[1]=13.0             ### call __setitem__
    obj['c0']=17.0          ### call __setitem__
    obj[3:5]=[21.0,22.0]    ### call __setitem__
    print(obj)
     
    print("---")
     
    v = obj[1:3]
    print(type(v))
    print(v.colnames)
    print(v.names)               
    print(v.Get('c2'))
    print(v['c2'])
     
    print(" ----- Test 2D ---- ")
    obj = NamedArray([arr,arr+10], names=['c0','c1','c2','c3','c4'])
    print(type(obj))
    print(obj.names)
    print(obj)        ### call __str__
    print(repr(obj))  ### call __repr__
    print(obj[1])     ### call __getitem__
    print(obj[:,1])   ### call __getitem__    ### Pb ...
    print(obj['c1'])  ### call __getitem__
    #print(obj[1,'c1']  ### call __getitem__    ### Pas encore possible)
    print(0.5*obj)
    print(obj+obj)
    obj[0,1]=13.0             ### call __setitem__
    print(obj)
    #obj['c0']=17.0          ### call __setitem__
    #obj[3:5]=[21.0,22.0]    ### call __setitem__
    #print(obj)
     
    print("---")
     
    v = obj[1:3]    ### besoin d'avoir un NamedArray1D !
    print(type(v))
    print(v.colnames)
    print(v.names)    
    print(v)           
    print(v.Get('c2'))
    print(v['c2'])
    Si jamais vous voyez d'autres solutions, ou bien une manière d'améliorer la piste que je suis en train d'explorer n'hésitez pas à m'en faire part.


    Lg_53

  6. #6
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Je reviens clore ce post après beaucoup de réflexion.

    La meilleure chose que je puisse faire dans mon cas, c'est finalement de créer une classe qui dérive de la classe numpy.ndarray. Même si ce n'est pas de la toute première évidence d'écrire une sous classe de numpy !


    Voici une bonne piste pour faire ça :

    http://www.python-forum.org/viewtopic.php?f=11&t=11306

    Ce code m'a bien aidé mais je l'ai réduits afin de gagner en performance en le limitant ses fonctionnalités aux usages dont j'ai besoin.

    Sachez tout de même que le simple fait de réécrire le getter (même sans rien mettre dedans):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def __getitem__(self,idx):
        return super().__getitem__(idx)
    coute un facteur 5 en temps d'éxécution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    --- Exec Time : Acces test 1.00e+06 simus
    0.12801289558410645   ### without __getitem__ rewrite
    0.6350655364990234     ### with __getitem__ rewrite
    On ne peut donc pas réduire plus que celà la pénalité que l'on prend sur le temps d'éxécution.

    Si ca peut servir à qqn...

    Merci à ceux qui ce sont intéressé à ce sujet.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2003] transfert de plusieurs lignes en une seule avec ajout des colonnes
    Par ghatfan99 dans le forum Excel
    Réponses: 0
    Dernier message: 10/08/2011, 20h33
  2. Réponses: 2
    Dernier message: 04/11/2010, 17h42
  3. Réponses: 2
    Dernier message: 21/10/2010, 17h23
  4. Réponses: 2
    Dernier message: 15/06/2009, 18h40
  5. Pb avec déplacement des colonnes dans Access
    Par sabredebois dans le forum IHM
    Réponses: 10
    Dernier message: 01/07/2008, 00h49

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