代码之家  ›  专栏  ›  技术社区  ›  Clay

有效地将numpy数组转换为pandas数组

  •  2
  • Clay  · 技术社区  · 7 年前

    如何有效地将numpy数组的numpy数组转换为数组列表?最终,我想让熊猫系列的数组成为一列是一个数据帧。如果有更好的方法可以直接达到这个目的,那也不错。

    以下可复制代码解决了 list() .tolist() ,但这两种方法都太慢,无法在我的实际数据集上实现。我在找更快的东西。

    import numpy as np 
    import pandas as pd
    
    a = np.array([np.array([0,1,2,3]), np.array([4,5,6,7])])
    
    s = pd.Series(a.tolist())
    
    s = pd.Series(list(a))
    

    这导致形状从 a.shape = (2,4) s.values.shape = (2,) .

    2 回复  |  直到 7 年前
        1
  •  2
  •   hpaulj    7 年前

    你的 a :

    In [2]: a = np.array([np.array([0,1,2,3]), np.array([4,5,6,7])])
       ...: 
    

    是(2,4)数字数组;我们本可以 a = np.array([[0,1,2,3],[4,5,6,7]]) . 创建数组的(2,)数组需要不同的构造。

    正如其他人所写,制作一个数据帧很简单:

    In [3]: pd.DataFrame(a)     # dtypes int64
    Out[3]: 
       0  1  2  3
    0  0  1  2  3
    1  4  5  6  7
    

    但是,从中进行一系列操作会产生一个错误:

    In [4]: pd.Series(a)
    ---------------------------------------------------------------------------
    ...
    Exception: Data must be 1-dimensional
    

    如果你的问题显示出这个错误,那么你的问题就会更清楚,为什么你要尝试列表输入:

    In [5]: pd.Series(a.tolist())
    Out[5]: 
    0    [0, 1, 2, 3]
    1    [4, 5, 6, 7]
    dtype: object
    In [6]: pd.Series(list(a))
    Out[6]: 
    0    [0, 1, 2, 3]
    1    [4, 5, 6, 7]
    dtype: object
    

    表面上它们是相同的,但是当我们看这个系列的实际元素时,我们看到一个包含列表,另一个包含数组。那是因为 tolist list() 从数组中创建不同的列表。

    In [8]: Out[5][0]
    Out[8]: [0, 1, 2, 3]
    In [9]: Out[6][0]
    Out[9]: array([0, 1, 2, 3])
    

    我的经验是 a.tolist() 相当快。 list(a) 相当于 [i for i in a] ;实际上它在 ,每次返回一个1d数组(行)。


    我们换衣服吧 所以它是一个1d对象数据类型数组:

    In [14]: a = np.array([np.array([0,1,2,3]), np.array([4,5,6,7]), np.array([1]), None])
    In [15]: a
    Out[15]: 
    array([array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([1]), None],
          dtype=object)
    

    现在我们可以从中制作一个系列:

    In [16]: pd.Series(a)
    Out[16]: 
    0    [0, 1, 2, 3]
    1    [4, 5, 6, 7]
    2             [1]
    3            None
    dtype: object
    In [17]: Out[16][0]
    Out[17]: array([0, 1, 2, 3])
    

    事实上,我们可以从 ,其中仅包含原始的两行:

    In [18]: pd.Series(a[:2])
    Out[18]: 
    0    [0, 1, 2, 3]
    1    [4, 5, 6, 7]
    dtype: object
    

    在其他SO问题中,我们已经深入讨论了构造1d对象dtype数组的技巧。

    请注意,这样的序列的行为不像多列数据帧。我看到有人试图编写csv文件,其中像这样的元素被保存为带引号的字符串。


    让我们比较一些构建时间:

    生成两种类型的较大数组:

    In [25]: a0 = np.ones([1000,4],int)
    In [26]: a1 = np.empty(1000, object)
    In [27]: a1[:] = [np.ones(4,int) for _ in range(1000)]
    # a1[:] = list(a0)   # faster
    

    首先生成数据帧:

    In [28]: timeit pd.DataFrame(a0)
    136 µs ± 919 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    这是同一时间 Out[3] ;显然,这只是用2d数组(任何大小)生成数据帧的开销 values .

    像你一样制作一个系列:

    In [29]: timeit pd.Series(list(a0))
    434 µs ± 12.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    In [30]: timeit pd.Series(a0.tolist())
    315 µs ± 5.64 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    这两个都比小的要长 ,反映了创作的迭代性。

    对于1d对象数组:

    In [31]: timeit pd.Series(a1)
    103 µs ± 1.66 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    这与小的一维数组相同。就像 In[28] 我想这只是创造一个 Series 对象,然后为其分配一个未更改的值数组。

    现在正在构建 a1 数组比较慢。

    像这样的对象数组 a1号 在很多方面就像一个列表-它包含指向内存中其他地方对象的指针。如果元素的类型不同(例如包含字符串或不包含字符串),则它可能很有用,但在计算上它不等同于二维数组。


    总之,如果源数组真的是1d对象数据类型数组,则可以快速创建 系列 从它。如果它真的是一个二维数组,您需要以某种方式,首先将其转换为列表或一维对象数组。

        2
  •  0
  •   Bal Krishna Jha    7 年前

    您可以从公共长度列表或列表列表的dict生成数据帧。在前一种情况下,pandas将键转换为列名,将列表转换为列值,在后一种情况下,每个列表都视为行。

    import numpy as np 
    import pandas as pd
    
    a = np.array([np.array([0,1,2,3]), np.array([4,5,6,7])])
    df = pd.DataFrame()
    df['a'] = a.tolist()
    df
    

    输出:

        a
    0   [0, 1, 2, 3]
    1   [4, 5, 6, 7]