Angenommen, ich mache so etwas wie:
val df = sqlContext.load("com.databricks.spark.csv", Map("path" -> "cars.csv", "header" -> "true"))
df.printSchema()
root
|-- year: string (nullable = true)
|-- make: string (nullable = true)
|-- model: string (nullable = true)
|-- comment: string (nullable = true)
|-- blank: string (nullable = true)
df.show()
year make model comment blank
2012 Tesla S No comment
1997 Ford E350 Go get one now th...
Aber ich wollte wirklich das year
as Int
(und vielleicht einige andere Spalten transformieren).
Das Beste, was ich mir einfallen lassen konnte, war
df.withColumn("year2", 'year.cast("Int")).select('year2 as 'year, 'make, 'model, 'comment, 'blank)
org.apache.spark.sql.DataFrame = [year: int, make: string, model: string, comment: string, blank: string]
das ist ein bisschen verworren.
Ich komme aus R und bin es gewohnt, schreiben zu können, z
df2 <- df %>%
mutate(year = year %>% as.integer,
make = make %>% toupper)
Ich vermisse wahrscheinlich etwas, da es in Spark / Scala einen besseren Weg geben sollte, dies zu tun ...
scala
apache-spark
apache-spark-sql
kevinykuo
quelle
quelle
Antworten:
Bearbeiten: Neueste Version
Seit Spark 2.x können Sie verwenden
.withColumn
. Überprüfen Sie die Dokumente hier:https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.sql.Dataset@withColumn(colName:String,col:org.apache.spark.sql.Column) : org.apache.spark.sql.DataFrame
Älteste Antwort
Seit Spark Version 1.4 können Sie die Cast-Methode mit DataType auf die Spalte anwenden:
Wenn Sie SQL-Ausdrücke verwenden, können Sie auch Folgendes tun:
Weitere Informationen finden Sie in den Dokumenten: http://spark.apache.org/docs/1.6.0/api/scala/#org.apache.spark.sql.DataFrame
quelle
df.withColumn("ctr", temp("ctr").cast(DecimalType(decimalPrecision, decimalScale)))
Spark 2.x
,df.withColumn(..)
können Sie je nachcolName
Argument eine Spalte hinzufügen oder ersetzen[EDIT: März 2016: Danke für die Stimmen! Obwohl wirklich, das ist nicht die beste Antwort, ich glaube , die Lösungen auf Basis von
withColumn
,withColumnRenamed
undcast
legte durch msemelman, Martin Senne und andere sind einfacher und sauberer].Ich denke, Ihr Ansatz ist in Ordnung. Denken Sie daran, dass ein Spark
DataFrame
eine (unveränderliche) RDD von Zeilen ist. Wir ersetzen also nie wirklich eine Spalte, sondern erstellenDataFrame
jedes Mal eine neue durch ein neues Schema.Angenommen, Sie haben eine Original-DF mit dem folgenden Schema:
Und einige UDFs, die in einer oder mehreren Spalten definiert sind:
Das Ändern von Spaltentypen oder sogar das Erstellen eines neuen DataFrame aus einem anderen kann folgendermaßen geschrieben werden:
was ergibt:
Dies kommt Ihrer eigenen Lösung ziemlich nahe. Wenn Sie die Typänderungen und andere Transformationen einfach getrennt halten
udf val
, wird der Code einfach lesbarer und wiederverwendbarer.quelle
NULL
oder fehlerhafter Eintrag einen ganzen Job zum Absturz bringt. Nicht effizient, da UDFs für Catalyst nicht transparent sind. Die Verwendung von UDFs für komplexe Operationen ist in Ordnung, aber es gibt keinen Grund, diese für das Gießen von Grundtypen zu verwenden. Deshalb haben wircast
Methode (siehe eine Antwort von Martin Senne ). Die Transparenz für Catalyst erfordert mehr Arbeit, aber die grundlegende Sicherheit ist nur eine Frage des PuttensTry
undOption
Arbeitens.withColumn()
Abschnitt auf einen generischen zu reduzieren , der alle Spalten durchläuft?Da die
cast
Operation für Spark verfügbar istColumn
(und ich persönlich dieudf
von @Svend
an dieser Stelle vorgeschlagenen nicht bevorzuge ), wie wäre es mit:auf den gewünschten Typ umwandeln? Als ordentliche Nebenwirkung, Werte nicht gießbaren / „konvertierbar“ in diesem Sinne wird worden
null
.Wenn Sie dies als Hilfsmethode benötigen , verwenden Sie:
welches verwendet wird wie:
quelle
Erstens , wenn Sie wollen , Typ umwandeln, dann das:
Bei gleichem Spaltennamen wird die Spalte durch eine neue ersetzt. Sie müssen keine Schritte hinzufügen und löschen.
Zweitens , etwa Scala vs R .
Dies ist der Code, der RI am ähnlichsten ist:
Obwohl die Codelänge etwas länger ist als die von R. Das hat nichts mit der Ausführlichkeit der Sprache zu tun. In R
mutate
ist dies eine spezielle Funktion für R-Datenrahmen, während Sie in Scala dank ihrer Ausdruckskraft problemlos eine Ad-hoc-Funktion verwenden können.Mit anderen Worten, es werden bestimmte Lösungen vermieden, da das Sprachdesign gut genug ist, um schnell und einfach Ihre eigene Domain-Sprache zu erstellen.
Randnotiz:
df.columns
ist überraschenderweise einArray[String]
stattArray[Column]
, vielleicht wollen sie, dass es wie der Datenrahmen von Python Pandas aussieht.quelle
import org.apache.spark.sql.types._
und dann stattsql.types.IntegerType
nurIntegerType
.Sie können es verwenden
selectExpr
, um es ein wenig sauberer zu machen:quelle
Java-Code zum Ändern des Datentyps des DataFrame von String in Integer
Der vorhandene (String-Datentyp) wird einfach in Integer umgewandelt.
quelle
DataTypes
reinsql.types
! es istDataType
. Darüber hinaus kann man einfach importierenIntegerType
und gießen.DataTypes.IntegerType
früher im DeveloperAPI-Modus und es ist stabil in v.2.1.0Um das Jahr von Zeichenfolge in int zu konvertieren, können Sie dem CSV-Reader die folgende Option hinzufügen: "inferSchema" -> "true", siehe DataBricks-Dokumentation
quelle
Dies funktioniert also nur dann wirklich, wenn Sie Probleme beim Speichern auf einem JDBC-Treiber wie sqlserver haben. Es ist jedoch sehr hilfreich bei Fehlern, die bei der Syntax und den Typen auftreten.
quelle
Generieren Sie einen einfachen Datensatz mit fünf Werten und konvertieren Sie ihn
int
in denstring
Typ:quelle
Ich denke, das ist für mich viel besser lesbar.
Dadurch wird Ihre Jahresspalte in konvertiert,
IntegerType
indem temporäre Spalten erstellt und diese Spalten gelöscht werden. Wenn Sie in einen anderen Datentyp konvertieren möchten, können Sie die Typen imorg.apache.spark.sql.types
Paket überprüfen .quelle
Die Antworten, die vorschlagen, Cast, FYI, die Cast-Methode in Spark 1.4.1, zu verwenden, sind fehlerhaft.
Beispielsweise hat ein Datenrahmen mit einer Zeichenfolgenspalte mit dem Wert "8182175552014127960", wenn er in bigint umgewandelt wird, den Wert "8182175552014128100".
Wir mussten uns vielen Problemen stellen, bevor wir diesen Fehler fanden, da wir Bigint-Spalten in der Produktion hatten.
quelle
quelle
Mit Spark Sql 2.4.0 können Sie Folgendes tun:
quelle
Sie können den folgenden Code verwenden.
Dadurch wird das Jahr Spalte für
IntegerType
Spalte konvertiert .quelle
Diese Methode löscht die alte Spalte und erstellt neue Spalten mit denselben Werten und neuem Datentyp. Meine ursprünglichen Datentypen bei der Erstellung des DataFrame waren: -
Danach habe ich folgenden Code ausgeführt, um den Datentyp zu ändern: -
Danach war mein Ergebnis: -
quelle
Sie können den Datentyp einer Spalte ändern, indem Sie cast in spark sql verwenden. Der Tabellenname ist Tabelle und hat nur zwei Spalten. Der Datentyp Spalte1 und Spalte2 und Spalte1 muss geändert werden. ex-spark.sql ("Wählen Sie cast (Spalte1 als Double) column1NewName, column2 aus der Tabelle") Anstelle von double schreiben Sie Ihren Datentyp.
quelle
Wenn Sie Dutzende von Spalten mit ihrem Namen umbenennen müssen, verwendet das folgende Beispiel den Ansatz von @dnlbrky und wendet ihn auf mehrere Spalten gleichzeitig an:
Nicht gegossene Spalten bleiben unverändert. Alle Spalten bleiben in ihrer ursprünglichen Reihenfolge.
quelle
So viele Antworten und nicht viele gründliche Erklärungen
Die folgende Syntax funktioniert mit Databricks Notebook mit Spark 2.4
Beachten Sie, dass Sie das Eingabeformat angeben müssen (in meinem Fall "MM-TT-JJJJ") und der Import obligatorisch ist, da to_date eine Spark-SQL-Funktion ist
Versuchte auch diese Syntax, bekam aber Nullen anstelle einer richtigen Besetzung:
(Hinweis: Ich musste Klammern und Anführungszeichen verwenden, damit es syntaktisch korrekt ist.)
PS: Ich muss zugeben, dass dies wie ein Syntaxdschungel ist, es gibt viele mögliche Einstiegspunkte und den offiziellen API-Referenzen fehlen geeignete Beispiele.
quelle
Eine andere Lösung ist wie folgt:
1) Behalten Sie "inferSchema" als falsch bei
2) Während Sie 'Map'-Funktionen in der Zeile ausführen, können Sie' asString 'lesen (row.getString ...)
quelle
Warum nicht einfach wie unter http://spark.apache.org/docs/latest/api/python/pyspark.sql.html#pyspark.sql.Column.cast beschrieben vorgehen?
quelle
quelle
Ein anderer Weg:
quelle
Für den Fall, dass Sie mehrere Spalten eines bestimmten Typs in einen anderen ändern möchten, ohne einzelne Spaltennamen anzugeben
quelle