2017-09-03 2 views
2

Ich habe ein Wörterbuch konvertieren, die wie folgt aussehen:Tupel in Reihen von zahlreichen Spalten in einer Pandas Dataframe

data = {'function_name': ['func1', 'func2', 'func3'], 
     'argument': [('func1_arg1', 'func1_arg2'), 
        ('func2_arg1',), 
        ('func3_arg1', 'func3_arg2', 'func3_arg3')], 
     'A': ['value_a1', 'value_a2', 'value_a3'], 
     'B': 'b', 
     'types': [('func1_type1', 'func1_type2'), 
        ('func2_type1',), 
        ('func3_type1', 'func3_type2', 'func3_type3')]} 

Ich möchte es in einen Pandas Datenrahmen konvertieren und es wie folgt aussehen:

function_name argument types   A   B 

func1   func1_arg1 func1_type1 value_a1 b 
func1   func1_arg2 func1_type2 value_a1 b 
func2   func2_arg1 func2_type1 value_a2 b 
func3   func3_arg1 func3_type1 value_a3 b 
func3   func3_arg2 func3_type2 value_a3 b 
func3   func3_arg3 func3_type3 value_a3 b 

Wie aus here folgt, wenn es eine Spalte von Tupeln wäre, hätte ich dies tun:

import pandas as pd 


data_frame = pd.DataFrame(data) 
new_frame = data_frame.set_index(['function_name','A','B'])['argument'].apply(pd.Series).stack().to_frame('argument').reset_index().drop('level_3',1) 

Aber wie gehe ich vor, wenn ich ein paar Tupelspalten habe?

EDIT:

Es scheint mit der genehmigten Lösung ein kleines Problem zu sein. Wenn nämlich eine Tuppled-Spalte vollständig aus Nones oder nur aus leeren Tupeln besteht, werden sie bei der Bildung der new_frame gelöscht. Ist es möglich, Pandas dazu zu bringen, die Spalten nicht fallen zu lassen?

Die Ausgangsdaten wie folgt aussehen:

data = {'function_name': ['func1', 'func2', 'func3'], 
     'argument': [('func1_arg1', 'func1_arg2'), 
        ('func2_arg1',), 
        ('func3_arg1', 'func3_arg2', 'func3_arg3')], 
     'A': ['value_a1', 'value_a2', 'value_a3'], 
     'B': 'b', 
     'types': [('func1_type1', 'func1_type2'), 
        ('func2_type1',), 
        ('func3_type1', 'func3_type2', 'func3_type3')], 
     'info': [(None, None), (None,), (None, None, None)]} 

Die 'info' Spalten könnten [(),(),()], das Ergebnis immer noch das gleiche sei.

Antwort

3

Da es mehrere Spalten zu erweitern gibt, denke ich nicht, dass dies in einer einzelnen Zeile sein kann, aber Sie können mit dem Konstruktor pd.DataFrame anwenden anwenden. Der Standardwert von dropna für die Stack-Methode ist True, also setzen Sie ihn auf false, um die None-Werte beizubehalten.

d.h
index = ['function_name','A','B'] 
new_frame = data_frame.set_index(index) 
      .apply(lambda x:pd.DataFrame(x.values.tolist()).stack(dropna=False),1) 
      .stack(dropna=False).reset_index().drop('level_3',1) 
new_frame.columns = index + [x for x in data_frame.columns if x not in index] 
 
    function_name A  B argument   types 
0 func1 value_a1  b func1_arg1 func1_type1 
1 func1 value_a1  b func1_arg2 func1_type2 
2 func2 value_a2  b func2_arg1 func2_type1 
3 func3 value_a3  b func3_arg1 func3_type1 
4 func3 value_a3  b func3_arg2 func3_type2 
5 func3 value_a3  b func3_arg3 func3_type3 

Mit drei Säulen

data = {'function_name': ['func1', 'func2', 'func3'], 
    'argument': [('func1_arg1', 'func1_arg2'), 
       ('func2_arg1',), 
       ('func3_arg1', 'func3_arg2', 'func3_arg3')], 
    'A': ['value_a1', 'value_a2', 'value_a3'], 
    'B': 'b', 
    'types': [('func1_type1', 'func1_type2'), 
       ('func2_type1',), 
       ('func3_type1', 'func3_type2', 'func3_type3')], 
    'info': [(None, None), (None,), (None, None, None)]} 
 
    function_name   A B argument info  types 
0   func1 value_a1 b func1_arg1 None func1_type1 
1   func1 value_a1 b func1_arg2 None func1_type2 
2   func2 value_a2 b func2_arg1 None func2_type1 
3   func3 value_a3 b func3_arg1 None func3_type1 
4   func3 value_a3 b func3_arg2 None func3_type2 
5   func3 value_a3 b func3_arg3 None func3_type3 

Hoffe, es hilft zu erweitern.

+1

Yep, wie es scheint, wie Charme funktioniert! Vielen Dank für Ihre Hilfe! – BigBear

+1

Ihre Begrüßung @bigbear – Dark

+0

@Parfait Vielen Dank für das Aufzeigen Ich aktualisierte die Antwort – Dark

2

Betrachten Sie eine verschachtelte Liste und dict comprehensions, wenn alle Elemente gleich lang sind (d. H. 3), indem Sie den DataFrame-Konstruktor verwenden. Nur Herausforderung ist die skalare Artikel 'B':'b' die am Ende zugeordnet werden können, wenn im Voraus bekannt:

dfs = [pd.DataFrame([{k:v[i] for k,v in data.items() if len(data[k])>1}][0]) \ 
      for i in range(len(data['function_name']))] 

df = pd.concat(dfs).reset_index(drop=True).assign(B='b') 

print(df) 
#   A argument function_name  types B 
# 0 value_a1 func1_arg1   func1 func1_type1 b 
# 1 value_a1 func1_arg2   func1 func1_type2 b 
# 2 value_a2 func2_arg1   func2 func2_type1 b 
# 3 value_a3 func3_arg1   func3 func3_type1 b 
# 4 value_a3 func3_arg2   func3 func3_type2 b 
# 5 value_a3 func3_arg3   func3 func3_type3 b 
+0

Können Sie versuchen, Ihre Lösung mit den drei Spalten erweitert werden? Daten, die ich in meiner Lösung bereitgestellt habe. Ihre Lösung verlangt, dass die Spalte typs gleich lang ist. – Dark

Verwandte Themen