Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Spark filter将多组行合并为一行_Apache Spark_Pyspark_Pyspark Sql - Fatal编程技术网

Apache spark Spark filter将多组行合并为一行

Apache spark Spark filter将多组行合并为一行,apache-spark,pyspark,pyspark-sql,Apache Spark,Pyspark,Pyspark Sql,我试图做到以下几点: 假设我有一个包含以下列的dataframe id | name | alias ------------------- 1 | abc | short 1 | abc | ailas-long-1 1 | abc | another-long-alias 2 | xyz | short_alias 2 | xyz | same_length 3 | def | alias_1 我想按id和名称分组并选择较短的别名 我期望

我试图做到以下几点:

假设我有一个包含以下列的dataframe

id  | name  | alias
-------------------
1   | abc   | short
1   | abc   | ailas-long-1
1   | abc   | another-long-alias
2   | xyz   | short_alias
2   | xyz   | same_length
3   | def   | alias_1
我想按id和名称分组并选择较短的别名

我期望的结果是

id  | name  | alias
-------------------
1   | abc   | short
2   | xyz   | short_alias
3   | def   | alias_1
我可以使用窗口和行数来实现这一点,是否有其他有效的方法来获得相同的结果。通常,第三列过滤器条件可以是字段长度的任意值

任何帮助都将不胜感激


谢谢。

您只需使用
length
内置函数,并在
窗口中使用该函数即可

from pyspark.sql import functions as f
from pyspark.sql import Window

windowSpec = Window.partitionBy('id', 'name').orderBy('length')

df.withColumn('length', f.length('alias'))\
    .withColumn('length', f.row_number().over(windowSpec))\
    .filter(f.col('length') == 1)\
    .drop('length')\
    .show(truncate=False)
应该给你什么

+---+----+-----------+
|id |name|alias      |
+---+----+-----------+
|3  |def |alias_1    |
|1  |abc |short      |
|2  |xyz |short_alias|
+---+----+-----------+

您只需使用
length
内置函数,并在
窗口中使用该函数即可

from pyspark.sql import functions as f
from pyspark.sql import Window

windowSpec = Window.partitionBy('id', 'name').orderBy('length')

df.withColumn('length', f.length('alias'))\
    .withColumn('length', f.row_number().over(windowSpec))\
    .filter(f.col('length') == 1)\
    .drop('length')\
    .show(truncate=False)
应该给你什么

+---+----+-----------+
|id |name|alias      |
+---+----+-----------+
|3  |def |alias_1    |
|1  |abc |short      |
|2  |xyz |short_alias|
+---+----+-----------+
一个没有窗口的解决方案(不是很漂亮…),在我看来,这是最简单的rdd解决方案:

from pyspark.sql import functions as F
from pyspark.sql import HiveContext
hiveCtx = HiveContext(sc)

rdd = sc.parallelize([(1   , "abc"   , "short-alias"),
                     (1   , "abc"   , "short"),
                         (1   , "abc"   , "ailas-long-1"),
                         (1   , "abc"   , "another-long-alias"),
                         (2   , "xyz"   , "same_length"),
                         (2   , "xyz"   , "same_length1"),
                         (3   , "def"   , "short_alias") ])

df = hiveCtx.createDataFrame(\
rdd, ["id", "name", "alias"])

len_df = df.groupBy(["id", "name"]).agg(F.min(F.length("alias")).alias("alias_len"))

df = df.withColumn("alias_len", F.length("alias"))

cond = ["alias_len", "id", "name"]

df.join(len_df, cond).show()

print rdd.map(lambda x: ((x[0], x[1]), x[2]))\
    .reduceByKey(lambda x,y: x if len(x) < len(y) else y ).collect()
一个没有窗口的解决方案(不是很漂亮…),在我看来,这是最简单的rdd解决方案:

from pyspark.sql import functions as F
from pyspark.sql import HiveContext
hiveCtx = HiveContext(sc)

rdd = sc.parallelize([(1   , "abc"   , "short-alias"),
                     (1   , "abc"   , "short"),
                         (1   , "abc"   , "ailas-long-1"),
                         (1   , "abc"   , "another-long-alias"),
                         (2   , "xyz"   , "same_length"),
                         (2   , "xyz"   , "same_length1"),
                         (3   , "def"   , "short_alias") ])

df = hiveCtx.createDataFrame(\
rdd, ["id", "name", "alias"])

len_df = df.groupBy(["id", "name"]).agg(F.min(F.length("alias")).alias("alias_len"))

df = df.withColumn("alias_len", F.length("alias"))

cond = ["alias_len", "id", "name"]

df.join(len_df, cond).show()

print rdd.map(lambda x: ((x[0], x[1]), x[2]))\
    .reduceByKey(lambda x,y: x if len(x) < len(y) else y ).collect()

看看您期望的数据帧,似乎简单的过滤器就可以做到这一点
df.filter(df['alias']=='short alias')
No,这些是示例,可以有任何值。我将对问题进行编辑,以使其更清晰。查看您预期的数据帧,似乎简单的过滤器就可以做到这一点
df.filter(df['alias']=='short alias')
No,这些是示例,可以有任何值。我将编辑这个问题,以明确上面代码中窗口的用途,我看不到它的用法。谢谢,我使用了您前面提到的使用行号的方法,因为我需要最后一列的长度最短。如果我先使用,它将无法确保其长度始终较短。我想知道是否还有其他方法。是的,你绝对正确@Murali。我又犯错误了。我已经更新了我的答案,请您接受并投票:谢谢我认为这是我心目中最好的方法。上面的代码中window的用途是什么,我看不出它的用法。谢谢,我使用了您前面提到的使用row_number的方法,因为我需要最后一列的长度最短。如果我先使用,它将无法确保其长度始终较短。我想知道是否还有其他方法。是的,你绝对正确@Murali。我又犯错误了。我已经更新了我的答案,请您接受并投票:谢谢我认为这是我心目中最好的方法。