2017-12-15 5 views
3

Ich habe ein Datenframe mit zwei Spalten: eine enthält eine Kategorie und die andere enthält einen 300-dimensionalen Vektor. Für jeden der Werte in der Kategorie-Spalte habe ich viele 300-dimensionale Vektoren. Was ich brauche, ist das Gruppieren des Datenrahmens durch die Kategorie-Spalte und gleichzeitig das Abrufen des Schwerpunktwertes aller Vektoren, die zu jeder Kategorie gehören.Python DataFrame - groupby und Schwerpunktberechnung

Category  Vector 
Balance  [1,2,1,-5,....,9] 
Inquiry  [-5,3,1,5,...,10] 
Card   [-3,1,2,3,...1] 
Balance  [1,3,-2,1,-5,...,7] 
Card   [3,1,3,4,...,2] 

also im obigen Fall würde der gewünschte Ausgang sein:

Category  Vector 
Balance  [1,2.5,-0.5,-2,....,8] 
Inquiry  [-5,3,1,5,...,10] 
Card   [0,1,2.5,3.5,...,1.5] 

I haben folgende Funktion schon geschrieben, die ein Array von Vektoren und berechnet seinen Schwerpunkt erhält:

import numpy as np 
    def get_intent_centroid(array): 
     centroid = np.zeros(len(array[0])) 
     for vector in array: 
      centroid = centroid + vector 
     return centroid/len(array)  

also brauche ich nur einen schnellen Weg, um die obige Funktion zusammen mit einem groupby Befehl auf dem Datenrahmen anzuwenden.

Bitte entschuldigen Sie meine Formatierung der Datenrahmen, aber ich weiß nicht, wie Sie sie richtig formatieren.

+0

Nicht sicher, wie man Manipulation von Vektoren in einer Spalte in Pandas, aber Sie können versuchen, diese 2 Spalten zu Listen zu ändern, und dann die Manipulation und konvertieren zurück zu Pandas! – Tarun

+0

Ich denke, dass das gesamte Berechnungsverfahren viel schneller wird, wenn ich keine Listen verwende. –

+0

@Tarun Wie würdest du mit Listen umgehen? –

Antwort

2

So ist der Schwerpunkt einer Liste von Vektoren ist nur der Mittelwert von jeweils Dimension der Vektoren, so kann dies nur sehr vereinfacht werden.

df.groupby('Category')['Vector'].apply(lambda x: np.mean(x.tolist(), axis=0))

Es sollte schneller als jede Schleife/list-Umwandlungsverfahren sein.

1

Wie die OP angefordert habe ich einen Weg, um es durch Listen zu tun:

vectorsList = list(df["Vector"]) 
catList = list(df["Category"]) 

#create a dict for each category and initialise it with a list of 300, zeros 
dictOfCats = {} 
for each in set(cat): 
    dictOfCats[each]= [0] * 300 

#loop through the vectorsList and catList 
for i in range(0, len(catList)): 
    currentVec = dictOfCats[each] 
    for j in range(0, len(vectorsList[i])): 
     currentVec[j] = vectorsList[i][j] + currentVec[j] 
    dictOfCats[each] = currentVec 

#now each element in dict has sum. you can divide it by the count of each category 
#you can calculate the frequency by groupby, here since i have used only lists, i am showing execution by lists 
catFreq = {} 
for eachCat in catList: 
    if(eachCat in catList): 
     catList[eachCat] = catList[eachCat] + 1 
    else: 
     catList[eachCat] = 1 


for eachKey in dictOfCats: 
    currentVec = dictOfCats[eachKey] 
    newCurrentVec = [x/catList[eachKey] for x in currentVec] 
    dictOfCats[eachKey] = newCurrentVec 

#now change this dictOfCats to dataframe again 

Bitte beachten Sie, dass Fehler im Code sein kann, da ich habe es nicht mit Ihren Daten überprüft. Dies wird rechenintensiv sein, aber sollte die Arbeit tun, wenn Sie nicht in der Lage sind, eine Lösung durch Pandas zu finden. Wenn Sie in Pandas mit einer Lösung kommen kann, schreibe die Antwort

0
import pandas as pd 
import numpy as np 

df = pd.DataFrame(
    [ 
     {'category': 'Balance', 'vector': [1,2,1,-5,9]}, 
     {'category': 'Inquiry', 'vector': [-5,3,1,5,10]}, 
     {'category': 'Card', 'vector': [-3,1,2,3,1]}, 
     {'category': 'Balance', 'vector': [1,3,-2,1,7]}, 
     {'category': 'Card', 'vector': [3,1,3,4,2]} 
    ] 
) 


def get_intent_centroid(array): 
    centroid = np.zeros(len(array[0])) 
    for vector in array: 
     centroid = centroid + vector 
    return centroid/len(array) 


df.groupby('category')['vector'].apply(lambda x: get_intent_centroid(x.tolist())) 

Output: 

category 
Balance [1.0, 2.5, -0.5, -2.0, 8.0] 
Card   [0.0, 1.0, 2.5, 3.5, 1.5] 
Inquiry [-5.0, 3.0, 1.0, 5.0, 10.0] 
Name: vector, dtype: object 
0

Dies sollte ohne die Verwendung von Listen arbeiten

def get_intent_centroid(array): 
    centroid = np.zeros(len(array.iloc[0])) 
    for vector in array: 
     centroid = centroid + vector 
    return centroid/len(array.iloc[0]) 

df.groupby('Catagory')['Vector'].apply(get_intent_centroid) 
Verwandte Themen