有效地写入pandas中的多个相邻列

toe*_*oes 5 python numpy pandas

使用numpy ndarray,可以一次写入多个列而无需先复制(只要它们相邻).如果我想写一个数组的前三列,我会写

a[0,0:3] = 1,2,3 # this is very fast ('a' is a numpy ndarray)
Run Code Online (Sandbox Code Playgroud)

我希望在熊猫中我同样能够通过"标签切片"选择多个相邻的列,如此(假设前3列标记为'a','b','c')

a.loc[0,'a':'c'] = 1,2,3 # this works but is very slow ('a' is a pandas DataFrame)
Run Code Online (Sandbox Code Playgroud)

或类似的

a.iloc[0,3:6] = 1,2,3 # this is equally as slow
Run Code Online (Sandbox Code Playgroud)

但是,与写入仅需几微秒的numpy数组相比,这需要几百毫秒.我不清楚大熊猫是否正在制作阵列的副本.我能找到以这种方式写入数据帧以提供良好速度的唯一方法是直接处理底层的ndarray

a.values[0,0:3] = 1,2,3 # this works fine and is fast
Run Code Online (Sandbox Code Playgroud)

我是否遗漏了Pandas文档中的内容,或者他们无法在Pandas数据帧上进行多个相邻列索引,速度可与numpy相媲美?

编辑

这是我正在使用的实际数据框架.

>> conn = sqlite3.connect('prath.sqlite')
>> prath = pd.read_sql("select image_id,pixel_index,skin,r,g,b from pixels",conn)
>> prath.shape
(5913307, 6)
>> prath.head()
   image_id  pixel_index  skin    r    g    b
0        21       113764     0    0    0    0
1        13       187789     0  183  149  173
2        17       535758     0  147   32   35
3        31         6255     0  116    1   16
4        15       119272     0  238  229  224
>> prath.dtypes
image_id       int64
pixel_index    int64
skin           int64
r              int64
g              int64
b              int64
dtype: object
Run Code Online (Sandbox Code Playgroud)

以下是不同索引方法的一些运行时比较(同样,pandas索引非常慢)

>> %timeit prath.loc[0,'r':'b'] = 4,5,6
1 loops, best of 3: 888 ms per loop
>> %timeit prath.iloc[0,3:6] = 4,5,6
1 loops, best of 3: 894 ms per loop
>> %timeit prath.values[0,3:6] = 4,5,6
100000 loops, best of 3: 4.8 µs per loop
Run Code Online (Sandbox Code Playgroud)

Joh*_*hnE 2

编辑澄清: 我不相信 pandas 在速度和语法方面与在 numpy 中设置视图有直接的相似之处。 就语法和目的而言,iloc和可能是最直接的模拟,但速度要慢得多。loc这是 numpy 和 pandas 中相当常见的情况。Pandas 比 numpy 做得更多(标记列/索引、自动对齐等),但不同程度地慢。当你需要速度并且可以在 numpy 中完成任务时,那么就在 numpy 中完成。


我认为简而言之,这里的权衡是,loc速度iloc会慢一些,但 100% 的时间都能工作,而values会很快,但并不总是有效(说实话,我什至没有意识到它会以你得到的方式工作)上班)。

但这是一个非常简单的示例,它values不起作用,因为列“g”是浮点数而不是整数。

prath['g'] = 3.33

prath.values[0,3:6] = 4,5,6

prath.head(3)

   image_id  pixel_index  skin    r     g    b
0        21       113764     0    0  3.33    0
1        13       187789     0  183  3.33  173
2        17       535758     0  147  3.33   35

prath.iloc[0,3:6] = 4,5,6

prath.head(3)

   image_id  pixel_index  skin    r     g    b
0        21       113764     0    4  5.00    6
1        13       187789     0  183  3.33  173
2        17       535758     0  147  3.33   35
Run Code Online (Sandbox Code Playgroud)

当列是同类类型时,您通常可以从 pandas 获得类似 numpy 的速度和行为,您需要小心这一点。 编辑添加:正如 @toes 在评论中指出的那样,文档确实指出您可以使用同类数据来执行此操作。然而,正如上面的示例所示,它可能非常容易出错,而且我认为很多人不会认为这是 pandas 中的良好通用实践。

我的一般建议是,如果您需要速度(并且具有同质数据类型),则在 numpy 中执行操作,如果不需要,则使用 pandas 执行操作。好处是 numpy 和 pandas 可以很好地协同工作,因此在数据帧和数组之间进行转换并不难。

编辑添加: 即使列“g”作为浮动,以下内容似乎也有效(尽管有警告)。速度介于values道与loc/iloc道之间。我不确定这是否可以一直有效。只是把它作为一种可能的中间道路提出来。

prath[0:1][['r','g','b']] = 4,5,6
Run Code Online (Sandbox Code Playgroud)