2017-05-08 180 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

相关问题