1
votes

list to pandas dataframe - Python

J'ai la liste suivante:

               Col1            Col2
var1         -0.146261   -0.8538301985671065
var2         0.017926   0.08182534201640915
var3         0.412654   0.40291331836021105

J'ai créé un pandas dataframe en utilisant le code suivant:

XXX

J'ai maintenant une nouvelle liste:

list2 = [-0.14626096918979603,
 0.017925919395027533,
 0.41265398151061766,
 -0.8538301985671065,
 0.08182534201640915,
 0.40291331836021105]

Je voudrais organiser le dataframe de manière à la sortie ressemble à ceci (MANUAL EDIT)

df = pd.DataFrame(list, index=['var1','var2','var3'], columns=['Col1'])
df
               Col1
var1         -0.146261
var2         0.017926
var3         0.412654

et que chaque fois qu'il y a une troisième ou première colonne ... les données sont organisées de la même manière. J'ai essayé de convertir la liste en un dict mais depuis que je suis nouveau avec python, je n'obtiens pas le résultat souhaité mais seulement des erreurs dues à des formes invalides.

- EDIT -

Une fois le dataframe créé, je veux le tracer en utilisant df.plot () . Cependant, la façon dont les données sont affichées n'est pas ce que je voudrais. Je viens de R donc je ne suis pas sûr si cela est dû à la structure de données utilisée dans le dataframe . Est-ce que j'ai besoin d'une mesure dans chaque ligne?

entrez la description de l'image ici

Mon idée serait d'avoir le col1 , col2 , col3 dans l'axe des x (c'est une série temporelle). Dans l'axe des y, la plage de valeurs (donc ça va dans ce tracé) et les lignes différentes devraient montrer l'évolution de var1 , var2 , var3 , etc.


4 commentaires

Votre liste 2 est-elle délibérément plus longue que la première colonne de votre DataFrame ou cette sortie finale n'est-elle qu'une tranche de la sortie réelle?


Je viens de modifier la question, j'ai mis la mauvaise list2 . list2 sera n'importe quel multiple de 3 donc son len serait 3,6,9. ... Le nombre ou les lignes dans df doivent toujours être 3 et les données doivent être "fractionnées" dans les colonnes. J'espère que c'est clair


pourquoi ne supprimez-vous pas les éléments communs dans la liste (veuillez utiliser un nom différent) et la liste 2 .. comme liste 2 = [i pour i dans la liste2 si je ne suis pas dans la liste] puis df ['Col2'] = liste2


@iamklaus lorsque je travaille avec les données, il arrive que je n'ai pas de list avec laquelle comparer mais que list2 sera produit directement. J'ai commencé à tester la conversion de list à df et j'aimerais maintenant passer au cas réel


4 Réponses :


2
votes

C'est ce que j'ai imaginé. Vous pouvez facilement le généraliser à plus de colonnes / lignes en définissant dynamiquement la forme

          c1        c2
v1 -0.146261 -0.853830
v2  0.017926  0.081825
v3  0.412654  0.402913

Et le résultat final ressemble à ceci:

import numpy as np
import pandas as pd

np_list = np.array(list2)
list_prep = np.transpose(np_list.reshape(2, 3))

df = pd.DataFrame(list_prep, index=['v1', 'v2', 'v3'], columns=['c1', 'c2'])


4 commentaires

Merci. Juste pour les autres qui pourraient être intéressés, je prévois de le rendre dynamique en utilisant index = [('v1', 'v2', 'v3') * n_rows] , où n_rows est un paramètre int qui mettra à l'échelle le nombre de lignes. Pour les colonnes , pas encore sûr car j'aurais besoin de quelque chose pour créer de nouvelles colonnes nommées c1 , c2 , c3 etc. . Fondamentalement, si la liste contient 9 valeurs, j'aurais besoin de 3 colonnes, si elle contient 12 puis 4 colonnes etc.


Ma réponse couvre cette dénomination automatique des colonnes.


@ArnoMaeckelberghe Je viens de le voir, je vais essayer tout de suite merci


@Artem Vovsia, j'ai édité la question pour ajouter un petit problème que j'ai lors du traçage du dataframe



2
votes

Pour nommer également automatiquement les colonnes en fonction du nombre de colonnes qui seront créées, vous pouvez:

import matplotlib.pyplot as plt

plt.plot(data.columns, data.T)
plt.legend(data.index)
plt.show()

Sortie:

          Col1      Col2
var1 -0.146261 -0.853830
var2  0.017926  0.081825
var3  0.412654  0.402913

Cela implique moins de codage en dur du nombre de colonnes / noms de colonnes.

Votre question modifiée sur le traçage est quelque chose de complètement différent, mais ici va quand même:

XXX

Votre tracé devrait avoir une meilleure apparence car vous avez plus de données, mais les données d'exemple n'avaient que deux colonnes:

 plot


5 commentaires

Je pense que vous voulez dire math.ceil au lieu de int - parce que int (7/3) vous donnerait 2 colonnes alors que OP en voudrait probablement 3 Colonnes


OP a précisé dans un commentaire sur sa question que: "list2 sera n'importe quel multiple de 3 donc son len serait 3,6,9 .... Le nombre ou les lignes de df devraient toujours être 3". Pour cette raison, je n'ai pas pris la peine d'importer un autre paquet.


@ArnoMaeckelberghe belle astuce pour la colonne. Cependant, je vois un problème avec cette option, si vous vérifiez l'ordre des valeurs dans les données n'est pas comme il est censé être. L'ordre correct peut être vu dans ma question et aussi dans la réponse @artem Vovsia. Peut-être qu'une combinaison des deux réponses, l'une pour nommer la colonne et l'autre pour obtenir les données dans l'autre correcte, fonctionnerait?


@GCGM bonne observation, a changé mon exemple pour donner la sortie correcte maintenant


@ArnoMaeckelberghe, j'ai édité la question pour ajouter un petit problème que j'ai lors du traçage du dataframe



1
votes

vous pouvez exécuter quelque chose comme

df = df.T

si la longueur de votre liste n'est pas un multiple de la longueur du dataframe ( len (list2)% len (df)! = 0 , vous devez étendre L (dans la dernière boucle) avec len (df) - (len (list2)% len (df)) valeurs NaN

pour répondre la deuxième question devrait être suffisante pour exécuter

df = pd.DataFrame(columns = ['var1', 'var2', 'var3'])
n_rows = int(np.ceil(len(list2) / len(df.columns)))
for ii in range(n_rows):
    L = list2[ii * len(df.columns) : (ii + 1) * len(df.columns)]
    df.loc['col_{}'.format(ii)] = L

pour la troisième question , alors il s'agit de savoir comment conçu à l'origine le dataframe. Vous pouvez modifier le code que nous avons écrit au début pour inverser les lignes et les colonnes

df.T.plot()

mais une fois que vous avez créé le dataframe avec la première méthode conçue, il n'y a rien de mal à exécuter p >

df = pd.DataFrame(index = ['var1', 'var2', 'var3'])

n_cols = int(np.ceil(len(list2) / len(df)))
for ii in range(n_cols):
    L = list2[ii * len(df) : (ii + 1) * len(df)]
    df['col_{}'.format(ii)] = L


8 commentaires

bien ça marche aussi. Je suis juste un peu perdu avec votre code. En essayant de comprendre ce qu'il fait réellement, je me perds (puisque je suis un peu nouveau en python). Pouvez-vous expliquer un peu les deux dernières lignes?


sûr: la ligne avant le dernier sélectionne un sous-ensemble de votre liste, en fonction de la boucle for dans laquelle vous vous trouvez. Disons que la première boucle prendra les éléments de la liste de l'index 0 à la longueur du dataframe, donc, dans ce cas, les 3 premiers éléments. Ensuite, ii augmente et cela prendra les éléments de 3 à 2 fois la longueur de la liste, c'est-à-dire les 3 éléments suivants et ainsi de suite. La dernière ligne affecte juste pour chaque boucle, la liste de sous-ensembles correspondante de 3 éléments à une nouvelle colonne qui sera nommée 'col_' et ensuite le numéro de la boucle (ii).


Merci beaucoup maintenant c'est clair. Btw, juste une curiosité: pourquoi utiliser ii au lieu de i . Est-ce une sorte de norme ou simplement une préférence personnelle?


juste question :) C'est juste une préférence personnelle, je ne sais même pas si c'est réellement une bonne utilisation (au cas où non, je m'excuse d'être trompeur). Disons que j'ai une liste x , j'aime généralement itérer ses éléments avec une boucle for comme for xx in x: , donc en cas de grandes boucles, je peux facilement récupérer d'où il vient. De plus, je peux immédiatement le reconnaître comme une variable qui changera sa valeur dans les différentes itérations de la boucle. Mais encore une fois, c'est juste une chose personnelle


J'ai modifié la question pour ajouter un petit problème que j'ai lors du traçage du dataframe


Je ne sais pas si j'ai totalement compris ce que vous voulez tracer. Les pandas tracent par défaut l'index sur le x , et la série de chaque colonne comme y avec des couleurs différentes pour chaque série. Si j'ai bien compris, vous aimeriez tracer le contraire, alors vous pouvez essayer df.T.plot () qui transposera d'abord le dataframe (.T) puis tracera. Sinon, vous pouvez utiliser le classique matplotlib.pyplot.plot et spécifier directement x et y.


En fait, df.T.plot () fonctionne très bien, mais ne serait-il pas "mieux" de créer le dataframe avec la bonne structure pour que df .plot le lit correctement?


Pour répondre, j'ai édité la première réponse, afin que le code soit un peu plus clair



0
votes

Solution simple

>>> pd.DataFrame({ 'a': list1, 'b': list2 })
          a         b
0 -0.146261 -0.146261
1  0.017926  0.017926
2  0.412654  0.412654
>>>

Remarque: veuillez vous assurer que le nombre d’éléments de la liste1 et de la liste2 est égal.


0 commentaires