2017-05-08 127 views
2

我有以下的數據幀:如何生成一個數據幀,該數據幀根據另一個的數量重複一個數據?

數據幀a

|---------------------| 
|  month  | 
|---------------------| 
|  2017-02-01  | 
|---------------------| 
|  2017-03-01  | 
|---------------------| 
|  2017-04-01  | 
|---------------------| 
|  2017-05-01  | 
|---------------------| 
|  2017-06-01  | 
|---------------------| 

數據幀b

|------------|---------------------|-----------------| 
|  beds |  model  |  units  | 
|------------|---------------------|-----------------| 
|  1  |   0.14  |  5  | 
|------------|---------------------|-----------------| 
|  2  |   0.26  |  9  | 
|------------|---------------------|-----------------| 

,我需要產生以下數據幀:

|------------|---------------------|-----------------|---------------------| 
|  beds |  model  |  units  |  month  | 
|------------|---------------------|-----------------|---------------------| 
|  1  |   0.14  |  5  |  2017-02-01  | 
|------------|---------------------|-----------------|---------------------| 
|  1  |   0.14  |  5  |  2017-03-01  | 
|------------|---------------------|-----------------|---------------------| 
|  1  |   0.14  |  5  |  2017-04-01  | 
|------------|---------------------|-----------------|---------------------| 
|  1  |   0.14  |  5  |  2017-05-01  | 
|------------|---------------------|-----------------|---------------------| 
|  1  |   0.14  |  5  |  2017-06-01  | 
|------------|---------------------|-----------------|---------------------| 
|  2  |   0.26  |  9  |  2017-02-01  | 
|------------|---------------------|-----------------|---------------------| 
|  2  |   0.26  |  9  |  2017-03-01  | 
|------------|---------------------|-----------------|---------------------| 
|  2  |   0.26  |  9  |  2017-04-01  | 
|------------|---------------------|-----------------|---------------------| 
|  2  |   0.26  |  9  |  2017-05-01  | 
|------------|---------------------|-----------------|---------------------| 
|  2  |   0.26  |  9  |  2017-06-01  | 
|------------|---------------------|-----------------|---------------------| 

我正在考慮使用一個for循環,但我想知道是否有一種方法可以在不使用循環的情況下在熊貓上進行。重點是b中的每一行都有一個新的行,並在a的對應月份。

回答

4

您可以根據a個月的值和b的索引值生成新的pd.MultiIndex。然後reindexpd.MultiIndex

mux = pd.MultiIndex.from_product([b.index, a.month], names=[None, 'month']) 
# included `reset_index(drop=True) on the advice from `@jezrael` 
# this replaces the non-unique index with a unique index 
b.reindex(mux, level=0).reset_index('month').reset_index(drop=True) 

     month beds model units 
0 2017-02-01  1 0.14  5 
1 2017-03-01  1 0.14  5 
2 2017-04-01  1 0.14  5 
3 2017-05-01  1 0.14  5 
4 2017-06-01  1 0.14  5 
5 2017-02-01  2 0.26  9 
6 2017-03-01  2 0.26  9 
7 2017-04-01  2 0.26  9 
8 2017-05-01  2 0.26  9 
9 2017-06-01  2 0.26  9 

簡單的指定水平和快速

%%timeit 
mux = pd.MultiIndex.from_product([b.index, a.month], names=[None, 'month']) 
b.reindex(mux, level=0).reset_index('month') 
1000 loops, best of 3: 1.46 ms per loop 

%timeit a.assign(id=1).merge(b.assign(id=1)).drop('id',1).sort_values("beds") 
100 loops, best of 3: 3.23 ms per loop 

%%timeit 
c = np.tile(a['month'].values, len(b.index)) 
d = np.repeat(b.index.values, len(a.index)) 
df = pd.DataFrame(b.values[d], index= b.index[d], columns=b.columns).assign(month=c) 
df.index = pd.RangeIndex(len(df.index)) 
df[['beds','units']] = df[['beds','units']].astype(int) 
1000 loops, best of 3: 1.28 ms per loop 
+0

@lmiguelvargasf歡迎您! – piRSquared

+0

嗯,在更大的df它也是快? – jezrael

+1

忘記重置索引 - 刪除重複索引值;) – jezrael

2

merge將使重複值笛卡爾乘積在合併列,這樣你就可以創建兩個數據幀的常數列,並在其合併:

df = a.assign(id=1).merge(b.assign(id=1)).drop('id',1) 
df.sort_values("beds") 

#  month beds model units 
#0 2017-02-01 1 0.14 5 
#2 2017-03-01 1 0.14 5 
#4 2017-04-01 1 0.14 5 
#6 2017-05-01 1 0.14 5 
#8 2017-06-01 1 0.14 5 
#1 2017-02-01 2 0.26 9 
#3 2017-03-01 2 0.26 9 
#5 2017-04-01 2 0.26 9 
#7 2017-05-01 2 0.26 9 
#9 2017-06-01 2 0.26 9 
+0

感謝,爲什麼你需要使用'分配(ID = 1)'?我認爲'merge()'默認執行了一個內部連接。 – lmiguelvargasf

+1

'assign(id = 1)'意味着在數據幀上創建一個連續鍵作爲連接鍵,以使結果成爲兩個數據幀的笛卡爾乘積。 – Psidom

3

Numpy溶液numpy.tilenumpy.repeat的重複:

c = np.tile(a['month'].values, len(b.index)) 
d = np.repeat(b.index.values, len(a.index)) 
df = pd.DataFrame(b.values[d], index= b.index[d], columns=b.columns).assign(month=c) 
df.index = pd.RangeIndex(len(df.index)) 
df[['beds','units']] = df[['beds','units']].astype(int) 
print (df) 

    beds model units  month 
0  1 0.14  5 2017-02-01 
1  1 0.14  5 2017-03-01 
2  1 0.14  5 2017-04-01 
3  1 0.14  5 2017-05-01 
4  1 0.14  5 2017-06-01 
5  2 0.26  9 2017-02-01 
6  2 0.26  9 2017-03-01 
7  2 0.26  9 2017-04-01 
8  2 0.26  9 2017-05-01 
9  2 0.26  9 2017-06-01 

print (df.dtypes) 
beds    int32 
model   float64 
units    int32 
month datetime64[ns] 
dtype: object 

另一種解決方案:

c = np.tile(a['month'].values, len(b.index)) 
d = np.tile(b.values, len(a.index)).reshape(-1,len(b.columns)) 
print (d) 
df = pd.DataFrame(d, columns=b.columns).assign(month=c) 
df[['beds','units']] = df[['beds','units']].astype(int) 
print (df) 
    beds model units  month 
0  1 0.14  5 2017-02-01 
1  1 0.14  5 2017-03-01 
2  1 0.14  5 2017-04-01 
3  1 0.14  5 2017-05-01 
4  1 0.14  5 2017-06-01 
5  2 0.26  9 2017-02-01 
6  2 0.26  9 2017-03-01 
7  2 0.26  9 2017-04-01 
8  2 0.26  9 2017-05-01 
9  2 0.26  9 2017-06-01 
+0

感謝您的回答,即使它解決了問題,我剛剛提高了喲,因爲有另一個答案似乎更簡單。 – lmiguelvargasf

+0

是的,它更簡單,但明顯更慢。所以如果非常大的df,'numpy'更好。 – jezrael

+0

我不知道,所以我打算使用'%timeit'來查看解決方案 – lmiguelvargasf

相關問題