我有一个数据框,该数据框的一列的值如下所示-
[[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))
我认为我可能必须将值展平,然后重塑。有什么想法要实现吗? 谢谢。
答案 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有一个清晰的了解,对于任何嵌套数组也应如此。