【问题标题】:Python Pandas - loc create fortran ordered numpy arrayPython Pandas - loc 创建 fortran 有序 numpy 数组
【发布时间】:2018-02-24 07:50:29
【问题描述】:

例如:

nrow = 10
ncol= 10
a = np.arange(nrow*ncol,dtype=np.int32).reshape(nrow,ncol)
a = pd.DataFrame(a)
ix_list = np.arange(nrow,dtype=np.int32)

print np.isfortran(a.values) #  False
print np.isfortran(a.loc[ix_list,:].values) #  True

为什么 .loc 使用 fortran 有序 numpy 数组创建 pandas 数据框?我可以强制它使用 C 有序 numpy 数组创建 pandas 数据框吗?

【问题讨论】:

  • 这个loc 生成的数组的shape 是什么?它的flags?
  • 你的意思是来自 a.loc[ix_list,:] 的 ndarray 的形状吗?它的形状与 a 相同,在本例中为 (10,10)。

标签: python pandas numpy


【解决方案1】:

无法回答您的第一个问题,但在您的数据框上调用 .values 将返回一个 numpy ndarray 所以:

希望对你有帮助!

【讨论】:

  • 非常感谢。我正在寻找一种强制 .loc 直接创建 C 有序 ndarray 以解决性能问题的方法。 np.ascontiguousarray() 与较大尺寸的 fortran 有序 ndarray 一起使用时速度较慢。
  • 好的,你能分享一下你的发现吗?
  • 对不起,我的意思是我找不到这样的方法。
  • 对不起,我的错。以防万一,转置你的数组怎么样?例如使用 a.loc[ix_list,:].transpose().values ?
  • 只是另一个问题,为什么需要使用 .loc ?您是否可以只使用 df 选择,例如:a[ix_list].values
【解决方案2】:
In [423]: adf = pd.DataFrame(a)
In [424]: ix_list = np.arange(nrow,dtype=np.int32)

您的问题索引创建了一个 F 有序数组,如 flagsstrides 所示。这是我在普通的 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 的数组不会复制。

在快速测试中,添加copynp.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)

【讨论】:

    猜你喜欢
    • 2015-12-16
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    相关资源
    最近更新 更多