In [423]: adf = pd.DataFrame(a)
In [424]: ix_list = np.arange(nrow,dtype=np.int32)
您的问题索引创建了一个 F 有序数组,如 flags 和 strides 所示。这是我在普通的 numpy 数组上执行 transpose 时期望看到的。
In [426]: adf.loc[ix_list].values.flags
Out[426]:
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
In [427]: adf.loc[ix_list].values.strides
Out[427]: (4, 40)
但其他loc 索引会产生一个C 顺序数组:
In [428]: adf.loc[:].values.flags
Out[428]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
....
In [429]: adf.loc[ix_list[::2]].values.flags
Out[429]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
...
In [430]: adf.loc[ix_list[:-2]].values.flags
Out[430]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
...
这看起来是 pandas loc 索引器中的错误。
我猜np.ascontiguousarray 是确保所有案例都是 C 排序的最便宜的方法,因为它执行np.array(..., copy=False),这是一个条件copy。已经是 C 的数组不会复制。
在快速测试中,添加copy 或np.ascontiguousarray 根本不会减慢速度。
In [439]: timeit np.ascontiguousarray(adf.loc[ix_list].values).flags
514 µs ± 7.07 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [440]: timeit adf.loc[ix_list].values.copy().flags
509 µs ± 5.94 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [441]: timeit adf.loc[ix_list].values.flags
513 µs ± 18.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [442]: timeit adf.loc[:].values.flags
24.9 µs ± 11.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [443]: timeit np.ascontiguousarray(adf.loc[:].values).flags
30 µs ± 865 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [444]: timeit adf.loc[ix_list[:-1]].values.flags
559 µs ± 12.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [445]: timeit np.ascontiguousarray(adf.loc[ix_list[:-1]].values).flags
559 µs ± 1.41 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
在 numpy 数组上选择行比使用 loc 快得多:
In [446]: timeit adf.loc[:].values[ix_list].flags
32.9 µs ± 1.33 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [447]: timeit adf.values[ix_list].flags
20.9 µs ± 1.09 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)