Вы можете использовать system
для запуска команды операционной системы из R.
Чтобы запустить java-банку в хорошо сконфигурированной системе, это должно работать:
system("java -jar /path/to/my.jar")
Вы можете добавить другие параметры, например, возможно, код Java принимает входные данные из файла, который вы пишете с помощью R, и передайте имя файла. Затем вывод из кода Java можно записать в файлы, а затем прочитать из R. Не зная, что делает код Java, мы не можем быть более конкретными.
Можно напрямую взаимодействовать с Java-кодом, но это требует полного знания внутренних компонентов банки, чтобы вы знали, какие функции вызывать с помощью каких параметров. Это обычно называют «API» для этой Java.
В противном случае напишите файл, вызовите system
, прочитайте файл, иногда это самый простой способ запускать код на других языках.
Spark 2.2 +
Вы можете использовать функцию explode_outer
:
import org.apache.spark.sql.functions.explode_outer
df.withColumn("likes", explode_outer($"likes")).show
// +---+----+--------+
// | id|name| likes|
// +---+----+--------+
// | 1|Luke|baseball|
// | 1|Luke| soccer|
// | 2|Lucy| null|
// +---+----+--------+
Spark & lt; = 2.1
В Scala, но эквивалент Java должен быть почти идентичны (для импорта отдельных функций используется import static
).
import org.apache.spark.sql.functions.{array, col, explode, lit, when}
val df = Seq(
(1, "Luke", Some(Array("baseball", "soccer"))),
(2, "Lucy", None)
).toDF("id", "name", "likes")
df.withColumn("likes", explode(
when(col("likes").isNotNull, col("likes"))
// If null explode an array<string> with a single null
.otherwise(array(lit(null).cast("string")))))
Идея здесь в основном заключается в том, чтобы заменить NULL
на array(NULL)
желаемого типа. Для сложного типа (aka structs
) вам необходимо предоставить полную схему:
val dfStruct = Seq((1L, Some(Array((1, "a")))), (2L, None)).toDF("x", "y")
val st = StructType(Seq(
StructField("_1", IntegerType, false), StructField("_2", StringType, true)
))
dfStruct.withColumn("y", explode(
when(col("y").isNotNull, col("y"))
.otherwise(array(lit(null).cast(st)))))
или
dfStruct.withColumn("y", explode(
when(col("y").isNotNull, col("y"))
.otherwise(array(lit(null).cast("struct<_1:int,_2:string>")))))
Примечание:
Если массив Column
] был создан с containsNull
установлен на false
, вы должны сначала изменить это (проверено с помощью Spark 2.1):
df.withColumn("array_column", $"array_column".cast(ArrayType(SomeType, true)))
Следуя принятому ответу, когда элементы массива являются сложным типом, его трудно определить вручную (например, с большими структурами).
Чтобы сделать это автоматически, я написал следующий помощник метод:
def explodeOuter(df: Dataset[Row], columnsToExplode: List[String]) = {
val arrayFields = df.schema.fields
.map(field => field.name -> field.dataType)
.collect { case (name: String, type: ArrayType) => (name, type.asInstanceOf[ArrayType])}
.toMap
columnsToExplode.foldLeft(df) { (dataFrame, arrayCol) =>
dataFrame.withColumn(arrayCol, explode(when(size(col(arrayCol)) =!= 0, col(arrayCol))
.otherwise(array(lit(null).cast(arrayFields(arrayCol).elementType)))))
}
data type mismatch: THEN and ELSE expressions should all be same type or coercible to a common type;
. Я пытаюсь сделать мой метод как можно более общим, поэтому он подходит для всех типов столбцов. – alexgbelov 28 September 2016 в 07:13dtypes
илиschema
. – zero323 28 September 2016 в 07:33isNotNull()
вместоisNotNull
). – zero323 12 April 2017 в 13:19