我有:
key value
a [1,2,3]
b [2,3,4]
我想:
key value1 value2 value3
a 1 2 3
b 2 3 4
似乎在scala中我可以写:df.select($"value._1", $"value._2", $"value._3")
,但在python中是不可能的。
那么有一个很好的方法吗?
答案 0 :(得分:26)
这取决于您的"列表":
的类型如果类型为ArrayType()
:
df = hc.createDataFrame(sc.parallelize([['a', [1,2,3]], ['b', [2,3,4]]]), ["key", "value"])
df.printSchema()
df.show()
root
|-- key: string (nullable = true)
|-- value: array (nullable = true)
| |-- element: long (containsNull = true)
您可以使用[]
df.select("key", df.value[0], df.value[1], df.value[2]).show()
+---+--------+--------+--------+
|key|value[0]|value[1]|value[2]|
+---+--------+--------+--------+
| a| 1| 2| 3|
| b| 2| 3| 4|
+---+--------+--------+--------+
+---+-------+
|key| value|
+---+-------+
| a|[1,2,3]|
| b|[2,3,4]|
+---+-------+
如果类型为StructType()
:(也许您是通过阅读JSON构建数据框)
df2 = df.select("key", psf.struct(
df.value[0].alias("value1"),
df.value[1].alias("value2"),
df.value[2].alias("value3")
).alias("value"))
df2.printSchema()
df2.show()
root
|-- key: string (nullable = true)
|-- value: struct (nullable = false)
| |-- value1: long (nullable = true)
| |-- value2: long (nullable = true)
| |-- value3: long (nullable = true)
+---+-------+
|key| value|
+---+-------+
| a|[1,2,3]|
| b|[2,3,4]|
+---+-------+
你可以直接分开'使用*
:
df2.select('key', 'value.*').show()
+---+------+------+------+
|key|value1|value2|value3|
+---+------+------+------+
| a| 1| 2| 3|
| b| 2| 3| 4|
+---+------+------+------+
答案 1 :(得分:1)
@jordi Aceiton感谢您的解决方案。 我试图使其更加简洁,尝试删除用于重命名新创建的列名的循环,并在创建列时进行了此操作。 使用df.columns来获取所有列名,而不是手动创建。
from pyspark.sql.types import *
from pyspark.sql.functions import *
from pyspark import Row
df = spark.createDataFrame([Row(index=1, finalArray = [1.1,2.3,7.5], c =4),Row(index=2, finalArray = [9.6,4.1,5.4], c= 4)])
#collecting all the column names as list
dlist = df.columns
#Appending new columns to the dataframe
df.select(dlist+[(col("finalArray")[x]).alias("Value"+str(x+1)) for x in range(0, 3)]).show()
输出:
+---------------+-----+------+------+------+
| finalArray |index|Value1|Value2|Value3|
+---------------+-----+------+------+------+
|[1.1, 2.3, 7.5]| 1 | 1.1| 2.3| 7.5|
|[9.6, 4.1, 5.4]| 2 | 9.6| 4.1| 5.4|
+---------------+-----+------+------+------+
答案 2 :(得分:1)
我需要将一个 712 维数组取消列出到列中,以便将其写入 csv。我首先使用@MaFF 的解决方案来解决我的问题,但这似乎导致了很多错误和额外的计算时间。我不确定是什么原因造成的,但我使用了一种不同的方法,该方法大大减少了计算时间(22 分钟,而超过 4 小时)!
@MaFF 的方法:
length = len(dataset.head()["list_col"])
dataset = dataset.select(dataset.columns + [dataset["list_col"][k] for k in range(length)])
我用过的:
dataset = dataset.rdd.map(lambda x: (*x, *x["list_col"])).toDF()
如果有人知道导致这种计算时间差异的原因,请告诉我!我怀疑在我的情况下,瓶颈在于调用 head()
来获取列表长度(我希望它是自适应的)。因为 (i) 我的数据管道很长而且很详尽,而且 (ii) 我不得不取消列出多个列。此外,缓存整个数据集也不是一种选择。
答案 3 :(得分:0)
我想在列表答案中添加大小写列表(数组)的大小写。
如果我们的列包含中型数组(或大型数组),仍然可以将它们拆分为列。
from pyspark.sql.types import * # Needed to define DataFrame Schema.
from pyspark.sql.functions import expr
# Define schema to create DataFrame with an array typed column.
mySchema = StructType([StructField("V1", StringType(), True),
StructField("V2", ArrayType(IntegerType(),True))])
df = spark.createDataFrame([['A', [1, 2, 3, 4, 5, 6, 7]],
['B', [8, 7, 6, 5, 4, 3, 2]]], schema= mySchema)
# Split list into columns using 'expr()' in a comprehension list.
arr_size = 7
df = df.select(['V1', 'V2']+[expr('V2[' + str(x) + ']') for x in range(0, arr_size)])
# It is posible to define new column names.
new_colnames = ['V1', 'V2'] + ['val_' + str(i) for i in range(0, arr_size)]
df = df.toDF(*new_colnames)
结果是:
df.show(truncate= False)
+---+---------------------+-----+-----+-----+-----+-----+-----+-----+
|V1 |V2 |val_0|val_1|val_2|val_3|val_4|val_5|val_6|
+---+---------------------+-----+-----+-----+-----+-----+-----+-----+
|A |[1, 2, 3, 4, 5, 6, 7]|1 |2 |3 |4 |5 |6 |7 |
|B |[8, 7, 6, 5, 4, 3, 2]|8 |7 |6 |5 |4 |3 |2 |
+---+---------------------+-----+-----+-----+-----+-----+-----+-----+
答案 4 :(得分:0)
添加到@MaFF 的答案中,对于数组类型数据,要动态执行此操作,您可以执行以下操作 df2.select(['key'] + [df2.features[x] for x in range(0,3)])
答案 5 :(得分:-2)
哦,我知道。您可以使用typename Container
。
getItem
诀窍。