2016-02-22 5 views
8
  1. Czy istnieje szybszy, bardziej pytonowy sposób robienia tego?
  2. Co to jest generowanie tego ostrzeżenia UserWarning: Boolean Series key will be reindexed to match DataFrame index. "DataFrame index.", UserWarning i czy powinienem się nim zajmować?

Mam plik csv z 3 kolumnami: org, month, person.W jaki sposób powinienem strukturyzować i uzyskać dostęp do tabeli danych, aby móc łatwo porównywać podzbiory w Pythonie 3.5?

| org | month | person | 
| --- | ---------- | ------ | 
| 1 | 2014-01-01 | 100 | 
| 1 | 2014-01-01 | 200 | 
| 1 | 2014-01-02 | 200 | 
| 2 | 2014-01-01 | 300 | 

które czytałem w pandas.core.frame.DataFrame z:

data = pd.read_csv('data_base.csv', names=['month', 'org', 'person'], skiprows=1) 

Ostatecznym celem jest porównanie przecięcie osób między 2 kolejnych okresach zbioru osób w pierwszym okresie.

org: 1, month: 2014-01-01, count(intersection((100, 200), 200))/len(set(100, 200)) == 0.5 

Edit: Dostałem go do pracy z:

import pandas as pd 
import sys 

data = pd.read_csv('data_base.csv', names=['month', 'org', 'person'], skiprows=1) 
data.sort_values(by=['org', 'month', 'person']) 

results = {} 
for _org in set(data.org): 
    results[_org] = {} 
    months = sorted(list(set(data[data.org == _org].month))) 
    for _m1, _m2 in zip(months, months[1:]): 
     _s1 = set(data[data.org == _org][data.month == _m1].person) 
     _s2 = set(data[data.org == _org][data.month == _m2].person) 
     results[_org][_m1] = float(len(_s1 & _s2)/len(_s1)) 
     print(str(_org) + '\t' + str(_m1) + '\t' + str(_m2) + '\t' + str(round(results[_org][_m1], 2))) 
     sys.stdout.flush() 

który wytwarza moc tak:

UserWarning: Boolean Series key will be reindexed to match DataFrame index. "DataFrame index.", UserWarning 
5640 2014-01-01 2014-02-01 0.75 
5640 2014-02-01 2014-03-01 0.36 
5640 2014-03-01 2014-04-01 0.6 
... 

Ale to bardzo powolny i rodzaj brzydki ... w obecna stawka, którą obliczam z powrotem na kopercie, szacuje ją na około 22 godziny dla dwuletniej partii danych.

+1

Pandy doskonale nadają się do pełnych operacji, a nie do krojenia.Czas dostępu do pojedynczego elementu jest rzędu 10-100 mikrosekund, co daje pełne 1000x, co można uzyskać za wyszukiwanie słownika (poniżej 50 ns). Kompromis to panda, która doskonale nadaje się do pełnowymiarowych lub kolumnowych obliczeń z dużymi danymi: długie czasy uruchomienia są ładnie wymieniane dzięki wyjątkowo szybkim, wektoryzowanym obliczeniom. Tutaj skutecznie wykonuje się kalkulacje element po elementach i konwersję z typów Pand, co oznacza, że ​​Panda, mimo że znakomita, nie jest odpowiednią biblioteką do tego zadania. –

Odpowiedz

3

Wprawdzie nigdy nie używałem Pand, więc może to nie być idiomatyczne. To po prostu używa podstawowych struktur Pythona.

import collections 
org_month_dict = collections.defaultdict(set) 

# put the data into a simple, indexed data structure 
for index, row in data.iterrows(): 
    org_month_dict[row['org'], row['month']].add(row['person']) 

orgs = set(data.org) 
months = sorted(set(data.months)) 
for org in orgs: 
    for mindex in range(len(months)-1): 
     m1 = months[mindex] 
     m2 = months[mindex+1] 
     print org_month_dict[org, m2] & org_month_dict[org, m1] # persons in common between month 1 and 2 

ta tworzy „pamięci podręcznej” tabeli odnośników w org_month_dict która jest indeksowana przez organizację i miesiąc, oszczędzając od robienia drogiego data[data.org == _org][data.month == _m1] wyszukiwanie w wewnętrznej pętli. Powinien działać znacznie szybciej niż oryginalny kod.

+0

On i tak nie powinien tu używać Pand (patrz mój komentarz powyżej w sekundę), więc jest to doskonała odpowiedź, używając poprawnego podejścia. –

+0

Dzięki za informacje na temat wad Pandas z prędkością krojenia. Sprawdziłem, jak czytać pliki CSV w Pythonie, a przykłady wykorzystywały funkcję read_csv Pandy, więc w ten sposób zszedłem na tę trasę. – zhespelt

1

Niekoniecznie tu odprawiłabym pandy. To zależy od kilku rzeczy. Nie sądzę, aby pandy były naprawdę kompaktowym sposobem przechowywania danych, mimo że posiadają one automatyczną kompresję i rzadkie opcje przechowywania, które w dużym stopniu to łagodzą. Spodziewam się, że szybkość będzie dość rozsądna, ale naprawdę trzeba ją przetestować na swoich danych, aby powiedzieć na pewno.

Oferuje (moim zdaniem) wygodniejszy sposób przechowywania danych, a także oferuje dogodne sposoby radzenia sobie z datami. A kiedy skończysz, możesz wysyłać wyniki w formie tabelarycznej.

Po pierwsze, zamierzam nieco rozszerzyć dane, aby lepiej przedstawić problemy.

org  month person 
0  1 2014-01-01  100 
1  1 2014-01-01  200 
2  1 2014-01-02  200 
3  1 2014-01-03  300 
4  1 2014-01-03  100 
5  1 2014-01-04  200 
6  1 2014-01-04  100 
7  1 2014-01-04  300 
8  2 2014-01-01  100 
9  2 2014-01-01  200 
10 2 2014-01-02  300 
11 2 2014-01-02  400 
12 2 2014-01-03  100 
13 2 2014-01-04  200 
14 2 2014-01-04  100 

Następnie można zrobić coś takiego:

df['one'] = 1 
df = df.set_index(['org','month','person']).unstack('person') 
numer = ((df==df.shift(-1)) & (df.notnull())).sum(axis=1) 
denom = df.notnull().sum(axis=1) 

df['numer'] = numer 
df['denom'] = denom 
df['ratio'] = numer/denom 

       one    numer denom  ratio 
person   100 200 300 400      
org month           
1 2014-01-01 1 1 NaN NaN  1  2 0.500000 
    2014-01-02 NaN 1 NaN NaN  0  1 0.000000 
    2014-01-03 1 NaN 1 NaN  2  2 1.000000 
    2014-01-04 1 1 1 NaN  2  3 0.666667 
2 2014-01-01 1 1 NaN NaN  0  2 0.000000 
    2014-01-02 NaN NaN 1 1  0  2 0.000000 
    2014-01-03 1 NaN NaN NaN  1  1 1.000000 
    2014-01-04 1 1 NaN NaN  0  2 0.000000 

jestem ignorując niektóre szczegóły tutaj, podobnie jak przerwania między org 1 i 2 org ale można dodać GroupBy sobie z tym poradzić . Podobnie, możesz chcieć dodać kod do obsługi dni bez obecności osoby i istnieją sposoby radzenia sobie z tym również.

+0

Czy możesz wyjaśnić linię '(df == df.shift (-1))'? – zhespelt

+0

To jest wartość logiczna pokazująca, które komórki pasują do powyższej komórki. Po prostu weź linię 'numer' i wydrukuj poszczególne jej części, aby uzyskać lepszy obraz tego, co robi. – JohnE

Powiązane problemy