J'ai un dictionnaire comme suit:
for header_name, body_list in all_unique.items():
for body_name in body_list:
metadata.loc[metadata.index[-1]] = [header_name, body_name]
Je voudrais créer un dataframe comme celui-ci:
+----+----------+--------+ | ID | header | body | +----+----------+--------+ | 1 | header_1 | body_1 | +----+----------+--------+ | 2 | header_1 | body_3 | +----+----------+--------+ | 3 | header_1 | body_2 | +----+----------+--------+ | 4 | header_2 | body_6 | +----+----------+--------+ | 5 | header_2 | body_4 | +----+----------+--------+ | 6 | header_2 | body_5 | +----+----------+--------+ | 7 | header_4 | body_7 | +----+----------+--------+
Où vide les éléments (comme pour la clé header_10 dans le dict ci-dessus) recevraient la valeur None . J'ai essayé un certain nombre de variétés pour df.loc telles que:
{'header_1': ['body_1', 'body_3', 'body_2'],
'header_2': ['body_6', 'body_4', 'body_5'],
'header_4': ['body_7', 'body_8'],
'header_3': ['body_9'],
'header_9': ['body_10'],
'header_10': []}
En vain. Il doit sûrement y avoir un moyen rapide dans panadas d'ajouter des lignes et d'auto-incrémenter l'index? Quelque chose de similaire à l'instruction SQL INSERT INTO utilisant uniquement du code pythonique?
Merci.
3 Réponses :
Ceci est un autre problème de désemboîtement
Empruntez la configuration de Jez pour votre d
def unnesting(df, explode):
idx=df.index.repeat(df[explode[0]].str.len())
df1=pd.concat([pd.DataFrame({x:np.concatenate(df[x].values)} )for x in explode],axis=1)
df1.index=idx
return df1.join(df.drop(explode,1),how='left')
Commencez par convertir votre dict en dataframe
yourdf=unnesting(df,[0])
yourdf
Out[208]:
0 index
0 body_1 header_1
0 body_3 header_1
0 body_2 header_1
1 body_6 header_2
1 body_4 header_2
1 body_5 header_2
2 body_7 header_4
2 body_8 header_4
3 body_9 header_3
4 body_10 header_9
5 None header_10
Puis en utilisant cette fonction dans ici
df=pd.Series(d).reset_index() df.columns Out[204]: Index(['index', 0], dtype='object')
d = {k: v if bool(v) else [None] for k, v in d.items()}
@jezrael ok laissez-moi supprimer ma réponse
Je pense que cette réponse est toujours valable car elle montre une approche alternative. Mais je préfère la méthode de @ jezrael car elle nécessite moins de lignes de code
@ user32882 pas de souci, sa réponse est meilleure à coup sûr
Si l'ensemble de données est trop volumineux, cette solution serait lente, mais elle devrait quand même fonctionner.
for key in data.keys():
vals= data[key]
# Create temp df with data from a single key
t_df = pd.DataFrame({'header':[key]*len(vals),'body':vals})
# Append it to your full dataframe.
df = df.append(t_df)
Utilisez la compréhension de dict pour ajouter Aucun s pour les listes vides, puis aplatir pour la liste des tuples:
data = []
for k, v in d.items():
if bool(v):
for y in v:
data.append((k, y))
else:
data.append((k, None))
df = pd.DataFrame(data, columns= ['a','b'])
print (df)
a b
0 header_1 body_1
1 header_1 body_3
2 header_1 body_2
3 header_2 body_6
4 header_2 body_4
5 header_2 body_5
6 header_4 body_7
7 header_4 body_8
8 header_3 body_9
9 header_9 body_10
10 header_10 None
Une autre solution:
d = {'header_1': ['body_1', 'body_3', 'body_2'],
'header_2': ['body_6', 'body_4', 'body_5'],
'header_4': ['body_7', 'body_8'],
'header_3': ['body_9'],
'header_9': ['body_10'],
'header_10': []}
d = {k: v if bool(v) else [None] for k, v in d.items()}
data = [(k, y) for k, v in d.items() for y in v]
df = pd.DataFrame(data, columns= ['a','b'])
print (df)
a b
0 header_1 body_1
1 header_1 body_3
2 header_1 body_2
3 header_2 body_6
4 header_2 body_4
5 header_2 body_5
6 header_4 body_7
7 header_4 body_8
8 header_3 body_9
9 header_9 body_10
10 header_10 None
Puis-je emprunter votre configuration pour d ?
Réponse très agréable / créative. Vous pouvez également utiliser if v au lieu de if bool (v) .
Et si vous transformiez simplement votre dictionnaire en quelque chose que les pandas pourraient gérer avant la main?
Ce serait inefficace, vous ne pensez pas? Cela introduirait du code supplémentaire ...
Plus inefficace que de tenter de réallouer la totalité du dataframe à chaque étape? Parce que c'est ce que cela fera.
À titre de comparaison, vous avez le dictionnaire, qui est une structure de données spécialement conçue pour être mutée efficacement. Plus de code ne signifie pas un code moins efficace.
@ W-B Je publierais à nouveau cette réponse. C'est précisément ce dont j'avais besoin