筛选位于pyspark.sql.dataframe单元格中的数组

时间:2018-10-10 18:22:07

标签: arrays dataframe pyspark

我对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

如果有人能告诉我如何解决这个问题,那将是很棒的事情。

2 个答案:

答案 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])

上面的答案为您在问题中提到的单独列表中的d1d2中提供了正确的结果。