2017-10-18 4 views
2

j'ai donc une dataframe de pandas géants de fichier csv ressemble à ceci:Python Pandas Dataframe: Comment créer des colonnes à partir d'une liste existante dans une base de données?

year,month,day,list 
2017,09,01,"[('United States of America', 12345), (u'Germany', 54321), (u'Switzerland', 13524), (u'Netherlands', 24135), ... ] 
2017,09,02,"[('United States of America', 6789), (u'Germany', 9876), (u'Switzerland', 6879), (u'Netherlands', 7968), ... ] 

Le nombre de paires count pays dans la 4ème colonne de chaque ligne n'est pas identique.
Je veux élargir la liste dans la 4ème colonne, et de transformer la trame de données en quelque chose comme ceci:

year,month,day,country,count 
2017,09,01,'United States of America',12345 
2017,09,01,'Germany',54321 
2017,09,01,'Switzerland',13524 
2017,09,01,'Netherlands',24135 
... 
2017,09,02,'United States of America',6789 
2017,09,02,'Germany',9876 
2017,09,02,'Switzerland',6879 
2017,09,02,'Netherlands',7968 
... 

Ma pensée était de générer 2 colonnes indépendantes, puis les rejoindre à l'origine dataframe. Peut-être quelque chose comme ceci:

country = df.apply(lambda x:[x['list'][0]]).stack().reset_index(level=1, drop=True) 
count = df.apply(lambda x:[x['list'][1]]).stack().reset_index(level=1, drop=True) 
df.drop('list', axis=1).join(country).join(count) 

Le code ci-dessus est certainement ne fonctionne pas (je l'espère juste peut aider à exprimer ma pensée), et je ne sais pas comment étendre les colonnes de date ainsi.
Toute aide ou suggestion est très appréciée.

Répondre

0

Probablement, la façon la plus simple de résoudre votre problème consiste à parcourir les tuples contenus dans la structure de données et à en créer une nouvelle. Vous pouvez le faire avec deux boucles imbriquées.

df_new = [] 
for i in df.itertuples(): 
    for l in i.list: 
     df_new.append([i.year, i.month, i.day, l[0], l[1]]) 

df_new = pd.DataFrame(df_new, columns=['year', 'month', 'day', 'country', 'count']) 

Si le quatrième champ de la liste n'est pas une liste réelle mais une chaîne (les guillemets doubles dans l'exemple de dataframe me laisser quelques doutes), vous pouvez utiliser la fonction literal_eval de la bibliothèque ast: Converting a string representation of a list into an actual list object

+0

Merci beaucoup! Je vais essayer de cette façon et voir si cela fonctionne. –

+0

Vous avez raison - la 4ème colonne n'était pas une liste réelle mais une chaîne, et votre méthode a résolu le problème avec la date. Je vous remercie! –

0

utilisation:

import ast 
#convert strings to lists of tuples 
df['list'] = df['list'].apply(ast.literal_eval) 
#create reshaped df from column list 
df1 =pd.DataFrame([dict(x) for x in df['list'].values.tolist()]).stack().reset_index(level=1) 
df1.columns = ['country','count'] 
#join to original 
df = df.drop('list', 1).join(df1).reset_index(drop=True) 
print (df) 
    year month day     country count 
0 2017  9 1     Germany 54321 
1 2017  9 1    Netherlands 24135 
2 2017  9 1    Switzerland 13524 
3 2017  9 1 United States of America 12345 
4 2017  9 2     Germany 9876 
5 2017  9 2    Netherlands 7968 
6 2017  9 2    Switzerland 6879 
7 2017  9 2 United States of America 6789 
+0

Merci! J'ai essayé et c'est exactement ce dont j'ai besoin. –

+0

BTW, j'ai trouvé quelque chose ne va pas avec la date, le problème est probablement avec la partie rejoin. Je mettrai à jour si je découvre comment le corriger. –

0

Alors, que vous avez besoin est de CConvert une colonne avec une liste de valeurs en plusieurs lignes. Une solution est de créer une nouvelle trame de données et faire une gauche join:

df = pd.DataFrame({'A':['a','b'],'B':['x','y'], 
        'C':[['a1', 'a2'],['b1', 'b2', 'b3']]}) 

df 
# A B    C 
# 0 a x  [[a1, a2]] 
# 1 b y [[b1, b2, b3]] 

dfr=df['C'].apply(lambda k: pd.Series(k)).stack().reset_index(level=1, drop=True).to_frame('C') 

dfr 
#  C 
# 0 a1 
# 0 a2 
# 1 b1 
# 1 b2 
# 1 b3 

df[['A','B']].join(dfr, how='left') 
# A B C 
# 0 a x a1 
# 0 a x a2 
# 1 b y b1 
# 1 b y b2 
# 1 b y b3 

Enfin, utilisez reset_index()

df[['A','B']].join(dfr, how='left').reset_index(drop=1) 
# A B C 
# 0 a x a1 
# 1 a x a2 
# 2 b y b1 
# 3 b y b2 
# 4 b y b3 

Crédit: https://stackoverflow.com/a/39955283/2314737

+0

Merci! Je vais essayer de cette façon aussi. –