重塑熊猫系列

时间:2020-07-26 01:43:46

标签: python pandas numpy

我有一个数据框,该数据框的一列的值如下所示-

[[3. , 2., 1.],[3. , 1., 2.]]

我正在读取此值,并将其作为熊猫系列传递给udf。下面是该系列的值的样子,下面的s类型是

s.values = [array([array([3. , 2., 1.]),
       array([3. , 1., 2.])], dtype=object)]

其形状显示为(1,)。我希望它的形状为1 X 2 X 3,但是使用下面的2种方法尝试执行此操作会出现如下所示的错误-

#gives error - ValueError: cannot reshape array of size 1 into shape (1,2,3)
s.values.reshape(1,2,3)

#gives error - ValueError: cannot reshape array of size 2 into shape (1,2,3)
s_array = np.array([s.tolist()])
s_array.reshape(1,2,3)

***********已添加 以下是我需要重塑的示例代码。它不能完全正常工作,但是执行它可以对问题有所了解。


import numpy as np
import pandas as pd
from pyspark.sql import SparkSession
from pyspark.sql.types import *
from pyspark.sql.functions import pandas_udf

spark = (
    SparkSession
    .builder
    .config("spark.sql.execution.arrow.enabled", "true")
    .getOrCreate()
    )

l = [['s1',[[3. , 2., 1.],[3. , 1., 2.]]], ['s2',[[4. , 2., 1.],[4. , 1., 2.]]]]
df = pd.DataFrame(l, columns = ['name','lst']) 

sparkDF =  spark.createDataFrame(df)

S_TYPE = ArrayType(ArrayType(DoubleType()))
def test(s):
   s_array = np.array([s.tolist()])
   #s_array.shape = (1, 1, 2)
   #ValueError: cannot reshape array of size 2 into shape (1,2,3)
   s_array.reshape(1,2,3)
   return s

test_udf = pandas_udf(test, S_TYPE)

df1 = sparkDF.withColumn("output", test_udf(sparkDF.lst))

我认为我可能必须将值展平,然后重塑。有什么想法要实现吗? 谢谢。

1 个答案:

答案 0 :(得分:1)

仅处理代码的熊猫部分:

In [138]: l = [['s1',[[3. , 2., 1.],[3. , 1., 2.]]], ['s2',[[4. , 2., 1.],[4. , 1., 2.]]]]           
In [139]: df = pd.DataFrame(l, columns = ['name','lst'])                                             
In [140]: df                                                                                         
Out[140]: 
  name                                 lst
0   s1  [[3.0, 2.0, 1.0], [3.0, 1.0, 2.0]]
1   s2  [[4.0, 2.0, 1.0], [4.0, 1.0, 2.0]]

具有2个元素的系列:

In [141]: df['lst']                                                                                  
Out[141]: 
0    [[3.0, 2.0, 1.0], [3.0, 1.0, 2.0]]
1    [[4.0, 2.0, 1.0], [4.0, 1.0, 2.0]]
Name: lst, dtype: object

to_numpy组成一个2元素对象dtype数组;系列中每个元素一个元素:

In [142]: df['lst'].to_numpy()                                                                       
Out[142]: 
array([list([[3.0, 2.0, 1.0], [3.0, 1.0, 2.0]]),
       list([[4.0, 2.0, 1.0], [4.0, 1.0, 2.0]])], dtype=object)
In [143]: _.shape                                                                                    
Out[143]: (2,)

或者我们可以从系列中创建一个嵌套列表:

In [144]: df['lst'].to_list()                                                                        
Out[144]: [[[3.0, 2.0, 1.0], [3.0, 1.0, 2.0]], [[4.0, 2.0, 1.0], [4.0, 1.0, 2.0]]]

从该列表中创建数组很容易(尤其是子列表的嵌套完全相同时):

In [145]: np.array(df['lst'].to_list())                                                              
Out[145]: 
array([[[3., 2., 1.],
        [3., 1., 2.]],

       [[4., 2., 1.],
        [4., 1., 2.]]])
In [146]: _.shape                                                                                    
Out[146]: (2, 2, 3)

to_numpy列表为1d,也可以是stack

In [147]: np.stack(df['lst'].to_numpy())                                                             
Out[147]: 
array([[[3., 2., 1.],
        [3., 1., 2.]],

       [[4., 2., 1.],
        [4., 1., 2.]]])

np.stack是一个concatenate版本,它将列表(或数组中的列表)连接到新轴上。默认情况下,它很像np.array;在这里,最好是“平整”嵌套。

如果l包含数组而不是嵌套列表,则大多数方法都可以使用。

其他

要使内容更接近您的初始s.values

In [174]: alist = [np.empty(2, object)]                                                              
In [175]: alist[0][:] = [np.array([3,2,1]),np.array([3,1,2])]                                        
In [176]: alist                                                                                      
Out[176]: [array([array([3, 2, 1]), array([3, 1, 2])], dtype=object)]
列表中的

stack并没有太大变化(仅构成(1,2)数组):

In [177]: np.stack(alist)                                                                            
Out[177]: array([[array([3, 2, 1]), array([3, 1, 2])]], dtype=object)

但列表中该元素的stack

In [178]: np.stack(alist[0])                                                                         
Out[178]: 
array([[3, 2, 1],
       [3, 1, 2]])

有时候,如果列表和数组的嵌套很复杂,我们必须尝试几种方法。密切注意列表和数组之间的区别,以及每个级别的len和/或shape

修改

让我们看一下对象数组的初始形状如何影响“堆栈”的拆包。

In [278]: df                                                                                         
Out[278]: 
  name                                 lst
0   s1  [[3.0, 2.0, 1.0], [3.0, 1.0, 2.0]]
1   s2  [[4.0, 2.0, 1.0], [4.0, 1.0, 2.0]]

如果按名称选择数据框列,则会得到一个系列:

In [279]: df['lst']                                                                                  
Out[279]: 
0    [[3.0, 2.0, 1.0], [3.0, 1.0, 2.0]]
1    [[4.0, 2.0, 1.0], [4.0, 1.0, 2.0]]
Name: lst, dtype: object

numpy格式为一维数组:

In [280]: df['lst'].to_numpy()                                                                       
Out[280]: 
array([list([array([3., 2., 1.]), array([3., 1., 2.])]),
       array([[4., 2., 1.],
       [4., 1., 2.]])], dtype=object)
In [281]: _.shape                                                                                    
Out[281]: (2,)

相反,如果我按列表选择一列,则会得到一个数据框:

In [282]: df[['lst']]                                                                                
Out[282]: 
                                  lst
0  [[3.0, 2.0, 1.0], [3.0, 1.0, 2.0]]
1  [[4.0, 2.0, 1.0], [4.0, 1.0, 2.0]]

numpy为2d:

In [283]: df[['lst']].to_numpy()                                                                     
Out[283]: 
array([[list([array([3., 2., 1.]), array([3., 1., 2.])])],
       [array([[4., 2., 1.],
       [4., 1., 2.]])]], dtype=object)
In [284]: _.shape                                                                                    
Out[284]: (2, 1)
1d数组的

stack将其解压缩并创建3d数组-一维来自外部数组,二维来自内部数组:

In [285]: np.stack(_280)                                                                             
Out[285]: 
array([[[3., 2., 1.],
        [3., 1., 2.]],

       [[4., 2., 1.],
        [4., 1., 2.]]])

但是2d的堆栈不会更改任何内容:

In [286]: np.stack(_283)                                                                             
Out[286]: 
array([[list([array([3., 2., 1.]), array([3., 1., 2.])])],
       [array([[4., 2., 1.],
       [4., 1., 2.]])]], dtype=object)

我们必须首先使用斜切,整形或索引将其设置为1d:

In [287]: np.stack(_283.ravel())                                                                     
Out[287]: 
array([[[3., 2., 1.],
        [3., 1., 2.]],

       [[4., 2., 1.],
        [4., 1., 2.]]])

我没有足够详细地关注您的代码以确切说明正在发生的事情,但是希望这可以使您对需要注意的事情有所了解。您需要对数组的形状和dtype有一个清晰的了解,对于任何嵌套数组也应如此。