将Pandas Series作为行有效地添加到现有数据框中

时间:2017-07-19 12:32:00

标签: pandas numpy

我有一个大约160k行乘24列的大型数据框。我还有一个长度为26的熊猫系列,我想逐行添加到我的数据框中,以形成一个160k行乘50列的最终数据帧,但我的代码非常缓慢。

具体来说这很慢,但它有效: final = df.apply(lambda x: x.append(my_series), axis=1)

产生正确的最终形状: Out[49]: (163008, 50)

其中,df.shapeOut[48]: (163008, 24)my_series.shapeOut[47]: (26,)

此方法适用于<50k行范围内的较小数据帧,但显然不太理想。

更新:为下面的解决方案添加了基准

使用%timeit对测试数据框和测试系列进行了一些测试,具有以下尺寸: test_df.shape

Out[18]: (156108, 24)

test_series.shape

Out[20]: (26,)

数据框和系列都包含字符串,浮点数,整数,对象等的混合。

使用Numpy接受的解决方案

%timeit test_df.join(pd.DataFrame(np.tile(test_series.values, len(test_df.index)).reshape(-1, len(attributes)), index=test_df.index, columns=test_series.index))

10 loops, best of 3: 220 ms per loop

使用assign: 我一直在接收ValueError: Length of values does not match length of index我的测试系列,但是如果我使用更简单的系列,只要它有效,不知道这里发生了什么......

使用@Divakar的自定义功能

%timeit rowwise_concat_df_series(test_df, test_series)

1 loop, best of 3: 424 ms per loop

3 个答案:

答案 0 :(得分:4)

我们可以使用DataFrame.assign()方法:

设定:

In [37]: df = pd.DataFrame(np.random.randn(5, 3), columns=['A','B','C'])

In [38]: my_series = pd.Series([10,11,12], index=['X','Y','Z'])

In [39]: df
Out[39]:
          A         B         C
0  1.129066  0.975453 -0.737507
1 -0.347736 -1.469583 -0.727113
2  1.158480  0.933604 -1.219617
3 -0.689830  3.063868  0.345233
4  0.184248  0.920349 -0.852213

In [40]: my_series
Out[40]:
X    10
Y    11
Z    12
dtype: int64

解决方案:

In [41]: df = df.assign(**my_series)

结果:

In [42]: df
Out[42]:
          A         B         C   X   Y   Z
0  1.129066  0.975453 -0.737507  10  11  12
1 -0.347736 -1.469583 -0.727113  10  11  12
2  1.158480  0.933604 -1.219617  10  11  12
3 -0.689830  3.063868  0.345233  10  11  12
4  0.184248  0.920349 -0.852213  10  11  12

注意:该系列应具有字符串索引元素。

PS **variable explained

答案 1 :(得分:3)

我认为您需要numpy.tile numpy.ndarray.reshape dfSeries df = pd.DataFrame({'A':list('abcdef'), 'B':[4,5,4,5,5,4], 'C':[7,8,9,4,2,3], 'D':[1,3,5,7,1,0], 'E':[5,3,6,9,2,4], 'F':list('aaabbb')}) print (df) A B C D E F 0 a 4 7 1 5 a 1 b 5 8 3 3 a 2 c 4 9 5 6 a 3 d 5 4 7 9 b 4 e 5 2 1 2 b 5 f 4 3 0 4 b s = pd.Series([1,5,6,7], index=list('abcd')) print (s) a 1 b 5 c 6 d 7 dtype: int64 值,最后join

df1 = pd.DataFrame(np.tile(s.values, len(df.index)).reshape(-1,len(s)), 
                   index=df.index, 
                   columns=s.index)
print (df1)
   a  b  c  d
0  1  5  6  7
1  1  5  6  7
2  1  5  6  7
3  1  5  6  7
4  1  5  6  7
5  1  5  6  7

df = df.join(df1)
print (df)
   A  B  C  D  E  F  a  b  c  d
0  a  4  7  1  5  a  1  5  6  7
1  b  5  8  3  3  a  1  5  6  7
2  c  4  9  5  6  a  1  5  6  7
3  d  5  4  7  9  b  1  5  6  7
4  e  5  2  1  2  b  1  5  6  7
5  f  4  3  0  4  b  1  5  6  7
EXPORTS
HeapAlloc = ntdll.RtlAllocateHeap

答案 2 :(得分:2)

看看是否有效 -

def rowwise_concat_df_series(df, s):
    a = df.values
    b = s.values

    m,n,r = a.shape + (b.size,)
    out_dtype = np.result_type(a.dtype, b.dtype)
    out_arr = np.empty((m, n + r),dtype=out_dtype)
    out_arr[:,:n] = a
    out_arr[:,n:] = b
    df_out = pd.DataFrame(out_arr)
    return df_out

示例运行 -

In [284]: df
Out[284]: 
   0  1
0  4  1
1  0  1
2  8  2
3  1  8
4  3  3

In [285]: s
Out[285]: 
0    5
1    8
2    2
dtype: int64

In [286]: rowwise_concat_df_series(df, s)
Out[286]: 
   0  1  2  3  4
0  4  1  5  8  2
1  0  1  5  8  2
2  8  2  5  8  2
3  1  8  5  8  2
4  3  3  5  8  2