2017-08-02 118 views
2

我有這樣一個組織的數據幀無關的數據...重新組織大熊貓

**Name** | **Mealtime** | **Food** 
John | 8:00 am | cereal 
John | 1:00 pm | salad 
John | 6:00 pm | pasta 
Sara | 8:00 am | yogurt 
Sara | 1:00 pm | panini 
Sara | 6:00 pm | steak 
Jake | 8:00 am | coffee 
Jake | 1:00 pm | burrito 
Jake | 6:00 pm | salad 

而且我需要它這樣

____| 8:00 am | 1:00 pm | 6:00 pm 
John | cereal | salad | pasta 
Sara | yogurt | panini | steak 
Jake | coffee | burrito | salad 

我怎麼會去這樣做組織?請注意,我並不是在尋找一種美學上的改變。最後,我想選擇一行數據,以可以從特定食物條目中確定名稱的方式將其饋入for循環。例如,抓住「1:00 pm」專欄,「沙拉」會指引我約翰。但如果我抓住了「下午6點」的專欄,「沙拉」會引導我到傑克。

回答

4

您需要df.pivot

In [606]: df.pivot(index='Name', columns='Mealtime', values='Food') 
Out[606]: 
Mealtime 1:00 pm 6:00 pm 8:00 am 
Name        
Jake  burrito salad coffee 
John  salad pasta cereal 
Sara  panini steak yogurt 
3

選項0
numpy切片與pd.factorize

我將使用pd.factorize生產整數值爲每一個獨特'Name''Mealtime'。除此之外,我也獲得了獨特的價值。每個整數值都對應於唯一值數組中該整數位置中的元素。

現在我知道唯一名稱的數量和獨特的進餐時間,所以我知道我最終的樞軸陣列的大小。所以我創建了一個空的,等待分配值。

由於我因式分解和因子是整數位置,我可以使用這些切片我的空陣列分配目的...所以我這樣做。最後,我將這一切與一個新的閃亮的數據框放在一起。

fn, un = pd.factorize(df.Name.values) 
fm, um = pd.factorize(df.Mealtime.values) 
v = np.empty((un.size, um.size), dtype=object) 
v[fn, fm] = df.Food.values 
pd.DataFrame(v, un, um) 

    8:00 am 1:00 pm 6:00 pm 
John cereal salad pasta 
Sara yogurt panini steak 
Jake coffee burrito salad 

選項1
使用​​/unstack

df.set_index(['Name', 'Mealtime']).Food.unstack() 

Mealtime 1:00 pm 6:00 pm 8:00 am 
Name        
Jake  burrito salad coffee 
John  salad pasta cereal 
Sara  panini steak yogurt 

選項2
使用defaultdict

from collections import defaultdict 

d = defaultdict(dict) 
[d[m].setdefault(n, f) for n, m, f in df.values]; 
pd.DataFrame(d) 

     1:00 pm 6:00 pm 8:00 am 
Jake burrito salad coffee 
John salad pasta cereal 
Sara panini steak yogurt 

選項3
蠻力

out = pd.DataFrame(index=df.Name.unique(), columns=df.Mealtime.unique()) 
[out.set_value(n, m, f) for n, m, f in df.values] 
out 

    8:00 am 1:00 pm 6:00 pm 
John cereal salad pasta 
Sara yogurt panini steak 
Jake coffee burrito salad 

時序
結論:使用pivot用於與純大熊貓較大的數據。在這種情況下很難打敗它的簡單性和完成工作的能力。但是如果你想以魯莽的速度轉彎,試試選項0

%%timeit 
fn, un = pd.factorize(df.Name.values) 
fm, um = pd.factorize(df.Mealtime.values) 
v = np.empty((un.size, um.size), dtype=object) 
v[fn, fm] = df.Food.values 
pd.DataFrame(v, un, um) 

%timeit df.set_index(['Name', 'Mealtime']).Food.unstack() 
%timeit df.pivot('Name', 'Mealtime', 'Food') 
%timeit d = defaultdict(dict); [d[m].setdefault(n, f) for n, m, f in df.values]; pd.DataFrame(d) 
%timeit out = pd.DataFrame(index=df.Name.unique(), columns=df.Mealtime.unique()); [out.set_value(n, m, f) for n, m, f in df.values]; out 

小數據

1000 loops, best of 3: 300 µs per loop 
1000 loops, best of 3: 1.82 ms per loop 
1000 loops, best of 3: 1.11 ms per loop 
1000 loops, best of 3: 541 µs per loop 
1000 loops, best of 3: 656 µs per loop 

較大的數據

from string import ascii_letters 

foods = np.array([ 
    'cereal', 'salad', 'pasta', 'yogurt', 
    'panini', 'steak', 'coffee', 'burrito' 
], dtype=object) 
times = pd.date_range(
    pd.datetime.now().date(), periods=24, freq='H' 
).strftime('%-I:00 %p') 
names = list(ascii_letters) 

idx = pd.MultiIndex.from_product([names, times], names=['Name', 'Mealtime']) 
df = pd.DataFrame(dict(
    Food=np.random.choice(foods, idx.size), 
), idx).reset_index() 

1000 loops, best of 3: 383 µs per loop 
1000 loops, best of 3: 1.99 ms per loop 
1000 loops, best of 3: 1.34 ms per loop 
100 loops, best of 3: 2.78 ms per loop 
100 loops, best of 3: 6.6 ms per loop 
+0

尼斯......計劃包括一個大型數據集的測試? –

+1

你走了... – piRSquared

+0

defaultdict方法比我想象的要好!讓我印象深刻。 –