С DataFrames
и UDF:
from pyspark.sql.types import ArrayType, StructType, StructField, IntegerType
from pyspark.sql.functions import col, udf
zip_ = udf(
lambda x, y: list(zip(x, y)),
ArrayType(StructType([
# Adjust types to reflect data types
StructField("first", IntegerType()),
StructField("second", IntegerType())
]))
)
(df
.withColumn("tmp", zip_("b", "c"))
# UDF output cannot be directly passed to explode
.withColumn("tmp", explode("tmp"))
.select("a", col("tmp.first").alias("b"), col("tmp.second").alias("c"), "d"))
С RDDs
:
(df
.rdd
.flatMap(lambda row: [(row.a, b, c, row.d) for b, c in zip(row.b, row.c)])
.toDF(["a", "b", "c", "d"]))
Оба решения неэффективны из-за накладных расходов на Python. Если размер данных исправлен, вы можете сделать что-то вроде этого:
from functools import reduce
from pyspark.sql import DataFrame
# Length of array
n = 3
# For legacy Python you'll need a separate function
# in place of method accessor
reduce(
DataFrame.unionAll,
(df.select("a", col("b").getItem(i), col("c").getItem(i), "d")
for i in range(n))
).toDF("a", "b", "c", "d")
или даже:
from pyspark.sql.functions import array, struct
# SQL level zip of arrays of known size
# followed by explode
tmp = explode(array(*[
struct(col("b").getItem(i).alias("b"), col("c").getItem(i).alias("c"))
for i in range(n)
]))
(df
.withColumn("tmp", tmp)
.select("a", col("tmp").getItem("b"), col("tmp").getItem("c"), "d"))
Это должно быть значительно быстрее по сравнению с UDF или RDD. Обобщены для поддержки произвольного количества столбцов:
# This uses keyword only arguments
# If you use legacy Python you'll have to change signature
# Body of the function can stay the same
def zip_and_explode(*colnames, n):
return explode(array(*[
struct(*[col(c).getItem(i).alias(c) for c in colnames])
for i in range(n)
]))
df.withColumn("tmp", zip_and_explode("b", "c", n=3))
Операторы +
и &
являются не одинаковыми в VB.NET.
Используя Оператор &
указывает на ваше намерение объединить строки, а оператор +
указывает на ваше намерение добавлять номера. Использование оператора &
преобразует обе стороны операции в строки. Когда у вас смешанные типы (одна сторона выражения - это строка, другая - число), ваше использование оператора будет определять результат.
1 + "2" = 3 'This will cause a compiler error if Option Strict is on'
1 & "2" = "12"
1 & 2 = "12"
"text" + 2 'Throws an InvalidCastException since "text" cannot be converted to a Double'
Итак, моя рекомендация (кроме как избежать таких как смешивание) заключается в использовании &
при конкатенации строк, чтобы убедиться, что ваши намерения понятны компилятору и избегают ошибок, которые невозможно найти, используя оператор +
для конкатенации.
Независимо от многочисленных подсказок «придерживаться одного ИЛИ другого» - это сильно зависит от того, что вы комбинируете.
Короче говоря, я бы использовал «& amp;». для строк и «+» только для арифметических операций
blockquote>Почему? Взгляните на https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/addition-operator#remarks
Все эти комбинации с переключением строгой опции похожи на то, как катить кости для компилятора ... и никогда не бывает очевидным для читателя.
Я также добавлю https://docs.microsoft.com / en-us / dotnet / visual-basic / programming-guide / language-features / operator-and-expressions / concatenation-operations # differ-between-the-two-concatenation-operations с понятным выражением:
Оператор + имеет основную цель добавления двух чисел.
blockquote>
Амперсанд является рекомендуемым методом. Оператор плюс будет работать, иногда, для конкатенации строк, но не считается правильным и будет иногда приводить к непредвиденным результатам.
Они идентичны в VB.NET при работе с 2 строками. «& Amp;» оператор существует для обратной совместимости в VB 6 и ранее, где & amp; был оператором конкатенации строк и + не работал для текста.
Существует разница, если один из двух операндов не является строкой, поскольку bdukes указал . Однако в этой ситуации я настоятельно рекомендую использовать String.Format или StringBuilder (в зависимости от количества / типов операций) для построения результирующей строки из смешанных типов.
В целом я бы рекомендовал использовать +, по одной причине. Если вы когда-либо решили перевести код на другой язык (например, C #), оператор + будет больше соответствовать переведенной версии. Вероятно, для людей, приезжающих с другого языка, будет легче понять и следовать вашему коду.
Подумайте, лучше ли использовать String.Format при конкатенации строк. Обычно код заканчивается тем, что имеет больше смысла.
Кроме того, если вы много раз объединяетесь, рассмотрите возможность использования StringBuilder, а не String.
В общем, & amp; всегда будет конкатенировать строки независимо от типов аргументов, а + не будет. Поскольку нет недостатка в использовании & amp; over + иначе, в ситуациях, когда вам явно нужны конкатенации строк, это предпочтительнее. Это также делает код более понятным.