我对PySpark还是陌生的,并且拥有一些Python经验。我已经能够过滤数据帧的行,并编写了udf来计算DataFrame单元格中数组的结果,结果为int或double。不,我需要一个数组作为输出,几个小时后我没有找到一个有用的例子。
这是问题所在:
DataFrame具有以下方案,其中number是同一DataFrame行的数组的条目数:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[]
grantResults) {
switch (requestCode) {
case REQUEST_AUDIO_PERMISSION_CODE:
if (grantResults.length> 0) {
boolean permissionToRecord = grantResults[0] ==
PackageManager.PERMISSION_GRANTED;
boolean permissionToStore = grantResults[1] ==
PackageManager.PERMISSION_GRANTED;
if (permissionToRecord && permissionToStore) {
Toast.makeText(getActivity().getApplicationContext(),
"Permission Granted", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity().getApplicationContext(),"Permission
Denied",Toast.LENGTH_LONG).show();
}
}
break;
}
}
这是一个名为df1的数据帧的示例:
DataFrame[number: int, code: array<string>, d1: array<double>, d2: array<double>]
现在,仅当我在DataFrame行的代码列的i位置中有“正确”字样时,我才想保留i的位置d1和d2。另外我想有一个新的数字New,剩余的职位数。生成的结构和DataFrame“ df2”应如下所示:
[4 ,['correct', 'correct', 'wrong', 'correct'], [33, 42, 35, 76], [12, 35, 15, 16]]
[2 ,['correct', 'wrong'], [47, 43], [13, 17]]
在其他几件事中(并基于一个在Python中成功的解决方案),我尝试了以下代码:
DataFrame[number: int, numberNew: int, code: array<string>, d1: array<double>, d2: array<double>]
[4 , 3, ['correct', 'correct', 'correct'], [33, 42, 76], [12, 35, 16]]
[2 , 1, ['correct'], [47], [13]]
我收到了一个很长且不太有用的错误消息。即有以下信息: TypeError:“浮动”对象没有属性“ getitem ”
如果有人能告诉我如何解决这个问题,那将是很棒的事情。
答案 0 :(得分:1)
您不能像这样从udf返回Pandas数据帧(还有其他支持此变量的变量,但是这些变量与您的逻辑不匹配),并且架构也始终与输出不匹配。像这样重新定义您的功能:
def filterDF(number, code, d1, d2):
dataFiltered = []
countNew = 0
for i in range(number):
if code[i] == 'correct':
dataFiltered.append([d1[i],d2[i]])
countNew += 1
return (countNew, dataFiltered)
filterDFudf = sqlContext.udf.register(
"filterDF", filterDF,
"struct<countNew: long, data: array<array<long>>>"
)
测试:
df = sqlContext.createDataFrame([
(4 ,['correct', 'correct', 'wrong', 'correct'], [33, 42, 35, 76], [12, 35, 15, 16]),
(2 ,['correct', 'wrong'], [47, 43], [13, 17])
]).toDF("number", "code", "d1", "d2")
df.select(filterDFudf("number", "code", "d1", "d2")).show()
# +------------------------------+
# |filterDF(number, code, d1, d2)|
# +------------------------------+
# | [3, [[33, 12], [4...|
# | [1, [[47, 13]]]|
# +------------------------------+
答案 1 :(得分:1)
对于其他解决方案,您还可以使用python中的列表理解功能:
def get_filtered_data(code, d1, d2):
indices = [i for i, s in enumerate(code) if 'correct' in s]
d1_ = [d1[index] for index in indices]
d2_ = [d2[index] for index in indices]
return [len(indices), d1_, d2_]
udf_get_filtered_data = udf(get_filtered_data, ArrayType(StringType()))
df = df.withColumn('filtered_data', udf_get_filtered_data('code', 'd1', 'd2'))
df.show()返回以下内容
+------+--------------------+----------------+----------------+--------------------+
|number| code| d1| d2| filtered_data|
+------+--------------------+----------------+----------------+--------------------+
| 4|[correct, correct...|[33, 42, 35, 76]|[12, 35, 15, 16]|[3, [33, 42, 76],...|
| 2| [correct, wrong]| [47, 43]| [13, 17]| [1, [47], [13]]|
+------+--------------------+----------------+----------------+--------------------+
顺便说一句,如果您使用
dataFiltered.append([d1[i],d2[i]])
它不会为您指定([33, 42, 76], [12, 35, 16])
的结果。相反,它将为您提供([33,12], [42,35], [76,16])
上面的答案为您在问题中提到的单独列表中的d1
和d2
中提供了正确的结果。