2013-10-08 18 views
37

Przechodzę z R do Pythona. Właśnie zacząłem używać Pandy. Mam kod R ładnie podzbiory:podzbiór Pythona DataFrame

k1 <- subset(data, Product = p.id & Month < mn & Year == yr, select = c(Time, Product)) 

Teraz chcę zrobić podobne rzeczy w Pythonie. to co mam do tej pory:

import pandas as pd 
data = pd.read_csv("../data/monthly_prod_sales.csv") 


#first, index the dataset by Product. And, get all that matches a given 'p.id' and time. 
data.set_index('Product') 
k = data.ix[[p.id, 'Time']] 

# then, index this subset with Time and do more subsetting.. 

zaczynam czuć, że robię to w niewłaściwy sposób. być może istnieje eleganckie rozwiązanie. Czy ktoś może pomóc? Muszę wyodrębnić miesiąc i rok z mojego znacznika czasu i wykonać podzestawy. Być może istnieje jeden liniowiec, który wykona to wszystko:

k1 <- subset(data, Product = p.id & Time >= start_time & Time < end_time, select = c(Time, Product)) 

dziękuję.

Odpowiedz

66

będę zakładać, że Time i Product są kolumny w DataFrame, df jest instancją DataFrame i że inne zmienne są wartości skalarne:

Na razie trzeba odwoływać się do instancji DataFrame:

k1 = df.loc[(df.Product == p_id) & (df.Time >= start_time) & (df.Time < end_time), ['Time', 'Product']] 

nawiasy są również konieczne ze względu na pierwszeństwo operatora & wobec operatorów porównawczych. Operator & jest w rzeczywistości przeciążonym operatorem bitowym, który ma taki sam priorytet jak operatory arytmetyczne, które z kolei mają wyższy priorytet niż operatory porównania.

W pandas 0.13 dostępna będzie nowa metoda eksperymentalna DataFrame.query(). Jest bardzo podobny do podzbioru modulo select argumentu:

Z query() zrobiłbyś to tak:

df[['Time', 'Product']].query('Product == p_id and Month < mn and Year == yr') 

Oto prosty przykład:

In [9]: df = DataFrame({'gender': np.random.choice(['m', 'f'], size=10), 'price': poisson(100, size=10)}) 

In [10]: df 
Out[10]: 
    gender price 
0  m  89 
1  f 123 
2  f 100 
3  m 104 
4  m  98 
5  m 103 
6  f 100 
7  f 109 
8  f  95 
9  m  87 

In [11]: df.query('gender == "m" and price < 100') 
Out[11]: 
    gender price 
0  m  89 
4  m  98 
9  m  87 

Ostateczna kwerendy, że jesteś zainteresowani będą nawet mogli skorzystać z przykutych porównań, takich jak:

k1 = df[['Time', 'Product']].query('Product == p_id and start_time <= Time < end_time') 
+0

Dzięki Philip. To dobrze działa. Tego właśnie szukałem - prostego, szybkiego rozwiązania. Wielkie dzięki jeszcze raz. Dla tych, którzy szukają takiego rozwiązania, użyty czas jest taki: (data.ts> = '2012-10-01') & (data.ts <'2013-05-01'). – user1717931

+0

Pewnie! Chętnie pomoże. –

+0

@Philip, próbowałem twojej sugestii z iPython z konkretnymi wartościami w moich warunkach. Pracowali dobrze. Ale kiedy osadzę to samo w programie i wywołam z parametrami, pojawia się błąd - końcowe wiersze to: 'code' Plik" /usr/local/lib/python2.7/dist-packages/pandas/core/series .py ", linia 225, w opakowaniu, jeśli len (samo)! = len (inne): Błąd typu: len() niezajętego obiektu – user1717931

14

Tylko dla kogoś szukającego rozwiązania bardziej podobny do R:

df[(df.Product == p_id) & (df.Time> start_time) & (df.Time < end_time)][['Time','Product']] 

Nie potrzeba data.loc lub query, ale ja sądzę, że jest trochę za długa.

5

Odkryłem, że możesz użyć dowolnego warunku podzbioru dla danej kolumny, owijając go w []. Na przykład, masz df z kolumnami [ „produkt”, „Time”, „Year”, „Kolor”]

I powiedzmy chcesz to produkty wykonane przed 2014. Można napisać,

df[df['Year'] < 2014] 

Aby zwrócić wszystkie wiersze, w których ma to miejsce. Możesz dodać różne warunki.

df[df['Year'] < 2014][df['Color' == 'Red'] 

Następnie wybierz kolumny, które chcesz, zgodnie z instrukcjami powyżej. Na przykład kolor produktu i klucz dla powyższego df,

df[df['Year'] < 2014][df['Color' == 'Red'][['Product','Color']] 
Powiązane problemy