2017-04-04 7 views
2

Ich versuche, zwei Datenrahmen oben und unten zu verketten. Nicht verketten Seite an Seite.Pandas: Merge zwei Spalten mit unterschiedlichen Namen?

Die Datenrahmen enthalten die gleichen Daten, jedoch könnte eine Spalte im ersten Datenrahmen den Namen "ObjectType" haben und im zweiten Datenrahmen könnte die Spalte den Namen "ObjectClass" haben. Als ich

df_total = pandas.concat ([df0, df1]) 

tun die df_total zwei Spaltennamen haben, eine mit „Objecttype“ und zum anderen mit „Object“. In jeder dieser zwei Spalten wird die Hälfte der Werte "NaN" sein. Also muss ich diese beiden Spalten manuell zu einem zusammenführen, was ein Schmerz ist.

Kann ich die beiden Spalten irgendwie zu einer zusammenführen? Ich möchte eine Funktion haben, die etwa so funktioniert:

df_total = pandas.merge_many_columns(input=["ObjectType,"ObjectClass"], output=["MyObjectClasses"] 

, die die beiden Spalten zusammenführt und eine neue Spalte erstellt. Ich habe in melt() geschaut, aber es tut das nicht wirklich?

(Vielleicht wäre es schön, wenn ich angeben könnte, was bei einer Kollision passieren wird, sagen wir, dass zwei Spalten Werte enthalten, dann gebe ich eine Lambda - Funktion mit dem Wert "keep the large value", " Durchschnitt“, etc)

Antwort

2

ich glaube, Sie Spalte zuerst für align Daten in beiden Datenrahmen umbenennen:

df0 = pd.DataFrame({'ObjectType':[1,2,3], 
        'B':[4,5,6], 
        'C':[7,8,9]}) 

#print (df0) 

df1 = pd.DataFrame({'ObjectClass':[1,2,3], 
        'B':[4,5,6], 
        'C':[7,8,9]}) 

#print (df1) 

inputs= ["ObjectType","ObjectClass"] 
output= "MyObjectClasses" 

#dict comprehension 
d = {x:output for x in inputs} 
print (d) 
{'ObjectType': 'MyObjectClasses', 'ObjectClass': 'MyObjectClasses'} 

df0 = df0.rename(columns=d) 
df1 = df1.rename(columns=d) 
df_total = pd.concat([df0, df1], ignore_index=True) 
print (df_total) 
    B C MyObjectClasses 
0 4 7    1 
1 5 8    2 
2 6 9    3 
3 4 7    1 
4 5 8    2 
5 6 9    3 

EDIT:

Mehr simplier ist update (Arbeits inplace):

df = pd.concat([df0, df1]) 
df['ObjectType'].update(df['ObjectClass']) 
print (df) 
    B C ObjectClass ObjectType 
0 4 7   NaN   1.0 
1 5 8   NaN   2.0 
2 6 9   NaN   3.0 
0 4 7   1.0   1.0 
1 5 8   2.0   2.0 
2 6 9   3.0   3.0 

Oder fillna, aber dann müssen ursprünglichen Spalten Spalten fallen:

df = pd.concat([df0, df1]) 
df["ObjectType"] = df['ObjectType'].fillna(df['ObjectClass']) 
df = df.drop('ObjectClass', axis=1) 
print (df) 
    B C ObjectType 
0 4 7   1.0 
1 5 8   2.0 
2 6 9   3.0 
0 4 7   1.0 
1 5 8   2.0 
2 6 9   3.0 

df = pd.concat([df0, df1]) 
df["MyObjectClasses"] = df['ObjectType'].fillna(df['ObjectClass']) 
df = df.drop(['ObjectType','ObjectClass'], axis=1) 
print (df) 
    B C MyObjectClasses 
0 4 7    1.0 
1 5 8    2.0 
2 6 9    3.0 
0 4 7    1.0 
1 5 8    2.0 
2 6 9    3.0 

EDIT1:

Timings:

df0 = pd.DataFrame({'ObjectType':[1,2,3], 
        'B':[4,5,6], 
        'C':[7,8,9]}) 

#print (df0) 

df1 = pd.DataFrame({'ObjectClass':[1,2,3], 
        'B':[4,5,6], 
        'C':[7,8,9]}) 

#print (df1) 
df0 = pd.concat([df0]*1000).reset_index(drop=True) 
df1 = pd.concat([df1]*1000).reset_index(drop=True) 

inputs= ["ObjectType","ObjectClass"] 
output= "MyObjectClasses" 

#dict comprehension 
d = {x:output for x in inputs} 

In [241]: %timeit df_total = pd.concat([df0.rename(columns=d), df1.rename(columns=d)], ignore_index=True) 
1000 loops, best of 3: 821 µs per loop 

In [240]: %%timeit 
    ...: df = pd.concat([df0, df1]) 
    ...: df['ObjectType'].update(df['ObjectClass']) 
    ...: df = df.drop(['ObjectType','ObjectClass'], axis=1) 
    ...: 

100 loops, best of 3: 2.18 ms per loop 

In [242]: %%timeit 
    ...: df = pd.concat([df0, df1]) 
    ...: df['MyObjectClasses'] = df['ObjectType'].combine_first(df['ObjectClass']) 
    ...: df = df.drop(['ObjectType','ObjectClass'], axis=1) 
    ...: 
100 loops, best of 3: 2.21 ms per loop 

In [243]: %%timeit 
    ...: df = pd.concat([df0, df1]) 
    ...: df['MyObjectClasses'] = df['ObjectType'].fillna(df['ObjectClass']) 
    ...: df = df.drop(['ObjectType','ObjectClass'], axis=1) 
    ...: 
100 loops, best of 3: 2.28 ms per loop 
+0

Ja, das könnte funktionieren zwei Spalten getrennt verschmelzen. Aber ich habe viele Spalten, und ich möchte nur zwei Spalten umbenennen. Funktioniert Ihre Lösung nur, wenn der Datenrahmen zwei Spalten hat? –

+0

Ich denke, es ist universelle Lösung - einfach die gleichen Spaltennamen in beiden Datenrahmen. – jezrael

+0

Danke für Ihre Hilfe, aber ich habe die Antwort mit "combinate_first" gewählt, weil es einfacher ist. :) –

1

Sie können von Nan in einen mit combine_first

>>> import numpy as np 
>>> import pandas as pd 
>>> 
>>> df0 = pd.DataFrame({'ObjectType':[1,2,3], 
        'B':[4,5,6], 
        'C':[7,8,9]}) 

>>> df1 = pd.DataFrame({'ObjectClass':[1,2,3], 
        'B':[4,5,6], 
        'C':[7,8,9]}) 

>>> df = pd.concat([df0, df1]) 
>>> df['ObjectType'] = df['ObjectType'].combine_first(df['ObjectClass']) 
>>> df['ObjectType'] 

0 1 
1 2 
2 3 
0 1 
1 2 
3 3 
Name: ObjectType, dtype: float64 
+0

Als ich das Op verstanden habe, hat er das df voll von Nan's nach dem Verketten bekommen und sucht nun nach einem Weg die beiden Spalten zusammenzuführen. – greole

+0

Genau das, was ich suchte. Danke! Vielleicht könntest du stattdessen das letzte lined editieren? Ich brauchte 15 Minuten um das herauszufinden, also würde ich mich freuen, wenn das hinzugefügt werden könnte: df ["ObjectType"] = df ['ObjectType']. Combine_first (df ['ObjectClass']) –

+0

Sorry, aber ich denke "update()" ist etwas pythonischer als "combinate_first()". Ich möchte beide als eine Lösung wählen. –

Verwandte Themen