2016-09-28 1 views
0

Sagen wir, ich habe einen Datenrahmen vom TypEffizientes sammeln Links in Datenrahmen

individual, location, food 
     1   A  a 
     1   A  b 
     1   B  a 
     1   A  c 
     2   C  a 
     2   C  b 

wo Einzelpersonen Verbindungen zwischen Lage und Essen schaffen. Ich möchte alle Links auf individueller Basis sammeln. Das heißt, wenn eine Person an den Standorten A und B und hatte (schließlich) Essen zu a beobachtet wurde, b und c, möchte ich alle diese Orte und Lebensmittelarten gegeneinander verlinken:

location food 
      A  a 
      A  b 
      A  c 
      B  a 
      B  b 
      B  c 
      C  a 
      C  b 

Eine - extrem ineffiziente - Vorgehensweise ist

import itertools 
def foo(group): 
    list1 = group.location.unique() 
    list2 = group.food.unique() 
    return pd.DataFrame(data=list(itertools.product(list1, list2)), columns=['location', 'food']) 
df.groupby(df.individual).apply(foo) 

Gibt es einen besseren Weg, dies zu tun?

Antwort

2

Sie können etwas Effizienz durch die Verwendung von numpy meshgrid.

import itertools 
import numpy as np 
def foo(group): 
    list1 = group.location.unique() 
    list2 = group.food.unique() 
    return pd.DataFrame(data=list(itertools.product(list1, list2)), columns=['location', 'food']) 

def bar(group): 
    list1 = group.location.unique() 
    list2 = group.food.unique() 
    product = np.meshgrid(list1, list2) 
    # reversing the order is necessary to get the same output as foo 
    list3 = np.dstack([product[1], product[0]]).reshape(-1, 2) 
    return pd.DataFrame(data=list3, columns=['location', 'food']) 

Auf meinem Rechner gab es eine kleine, (~ 20%) Speedup

In [66]: %timeit df.groupby(df.individual).apply(foo) 
100 loops, best of 3: 2.57 ms per loop 

In [67]: %timeit df.groupby(df.individual).apply(bar) 
100 loops, best of 3: 2.16 ms per loop