2016-08-08 7 views
2

Angesichts der folgenden Datenrahmen:Pandas Flag Reihen mit Complementary Zeros

import pandas as pd 
df=pd.DataFrame({'A':[0,4,4,4], 
       'B':[0,4,4,0], 
       'C':[0,4,4,4], 
       'D':[4,0,0,4], 
       'E':[4,0,0,0], 
       'Name':['a','a','b','c']}) 
df 
    A B C D E Name 
0 0 0 0 4 4 a 
1 4 4 4 0 0 a 
2 4 4 4 0 0 b 
3 4 0 4 4 0 c 

Ich möchte ein neues Feld hinzufügen „Match_Flag“, die einzigartige Kombinationen von Reihen-Etiketten, wenn sie ergänzende Null-Muster haben (wie bei Zeilen 0, 1 und 2) UND haben denselben Namen (nur für Zeilen 0 und 1). Es verwendet den Namen der übereinstimmenden Zeilen.

Das gewünschte Ergebnis ist wie folgt:

A B C D E Name Match_Flag 
0 0 0 0 4 4 a  a 
1 4 4 4 0 0 a  a 
2 4 4 4 0 0 b  NaN 
3 4 0 4 4 0 c  NaN 

Caveat: Die Muster können variieren, aber immer noch komplementär sein sollte.

Vielen Dank im Voraus!

UPDATE

Sorry für die Verwirrung. Hier ist eine Klarstellung:

Der Grund, warum Zeilen 0 und 1 "komplementär" sind, ist, dass sie entgegengesetzte Muster von Nullen in ihren Spalten haben; 0,0,0,4,4 vs, 4,4,4,0,0. Die Zahl 4 ist beliebig; es könnte genauso gut 0,0,0,4,2 und 65,770,23,0,0 sein. Wenn zwei solcher Zeilen tatsächlich komplementär sind und denselben Namen haben, möchte ich, dass sie unter der Spalte "Match_Flag" mit demselben Namen gekennzeichnet werden.

+0

nie Leiter der "kostenlose", bitte erläutern. – Merlin

+0

Was ich mit komplementär verstehe, ist, dass die Spalten in einer Zeile, die Null sind, in einem anderen nicht Null sind, und umgekehrt. Deshalb sind die ersten 2 Zeilen kostenlos; Sie haben Nullen in entgegengesetzten Spalten. –

Antwort

2

Sie können ein Kompliment identifizieren, wenn das Skalarprodukt Null ist und die elementweise Summe null ist.

def complements(df): 
    v = df.drop('Name', axis=1).values 
    n = v.shape[0] 
    row, col = np.triu_indices(n, 1) 

    # ensure two rows are complete 
    # their sum contains no zeros 
    c = ((v[row] + v[col]) != 0).all(1) 
    complete = set(row[c]).union(col[c]) 

    # ensure two rows do not overlap 
    # their product is zero everywhere 
    o = (v[row] * v[col] == 0).all(1) 
    non_overlap = set(row[o]).union(col[o]) 

    # we are a compliment iff we do 
    # not overlap and we are complete 
    complement = list(non_overlap.intersection(complete)) 

    # return slice 
    return df.Name.iloc[complement] 

Dann groupby('Name') und apply unsere Funktion

df['Match_Flag'] = df.groupby('Name', group_keys=False).apply(complements) 

enter image description here

+1

Ich denke, dass das Skalarprodukt Null ist, ist eine notwendige Bedingung, aber nicht ausreichend. Der Kommentar des OP sagt, dass "Spalten in einer Reihe, die Null sind, in einem anderen nicht Null sind". Hieraus ergibt sich, daß, wenn zwei Zeilen in der gleichen Spalte eine Null haben, sie nicht komplementär sind, sondern ein Punktprodukt von Null, z. '[4,0,0]' und '[0,0,4]'. Wenn es negative Werte gibt, könnten Sie auch ein Null-Punkt-Produkt erhalten, selbst wenn alle Einträge nicht Null sind, z. '[1, -1,1]' und '[1,2,1]'. – root

+0

@root hat es behoben. – piRSquared

Verwandte Themen