Bir Spark DataFrame'e sabit bir sütun nasıl eklenir?


138

Bir sütun eklemek istiyorum DataFramebazı rasgele değeri olan (her satır için aynıdır). withColumnAşağıdaki gibi kullandığımda bir hata alıyorum :

dt.withColumn('new_column', 10).head(5)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-50-a6d0257ca2be> in <module>()
      1 dt = (messages
      2     .select(messages.fromuserid, messages.messagetype, floor(messages.datetime/(1000*60*5)).alias("dt")))
----> 3 dt.withColumn('new_column', 10).head(5)

/Users/evanzamir/spark-1.4.1/python/pyspark/sql/dataframe.pyc in withColumn(self, colName, col)
   1166         [Row(age=2, name=u'Alice', age2=4), Row(age=5, name=u'Bob', age2=7)]
   1167         """
-> 1168         return self.select('*', col.alias(colName))
   1169 
   1170     @ignore_unicode_prefix

AttributeError: 'int' object has no attribute 'alias'

Diğer sütunlardan birini ekleyerek ve çıkararak (böylece sıfıra ekler) ve sonra istediğim sayıyı (bu durumda 10) ekleyerek işlevi istediğiniz gibi çalıştırabilirim:

dt.withColumn('new_column', dt.messagetype - dt.messagetype + 10).head(5)
[Row(fromuserid=425, messagetype=1, dt=4809600.0, new_column=10),
 Row(fromuserid=47019141, messagetype=1, dt=4809600.0, new_column=10),
 Row(fromuserid=49746356, messagetype=1, dt=4809600.0, new_column=10),
 Row(fromuserid=93506471, messagetype=1, dt=4809600.0, new_column=10),
 Row(fromuserid=80488242, messagetype=1, dt=4809600.0, new_column=10)]

Bu son derece hileli, değil mi? Bunu yapmanın daha yasal bir yolu olduğunu varsayıyorum?

Yanıtlar:


221

Kıvılcım 2.2+

2.2 tanıtır Spark typedLitdesteklemek Seq, Mapve Tuples( SPARK-19254 ) ve aşağıdaki çağrılar desteklenmelidir (Scala):

import org.apache.spark.sql.functions.typedLit

df.withColumn("some_array", typedLit(Seq(1, 2, 3)))
df.withColumn("some_struct", typedLit(("foo", 1, 0.3)))
df.withColumn("some_map", typedLit(Map("key1" -> 1, "key2" -> 2)))

Spark 1.3+ ( lit), 1.4+ ( array, struct), 2.0+ ( map):

İçin ikinci argüman bir DataFrame.withColumnolmalıdır, bu Columnyüzden bir literal kullanmak zorundasınız:

from pyspark.sql.functions import lit

df.withColumn('new_column', lit(10))

Karmaşık sütunlara ihtiyacınız varsa, bunları aşağıdaki gibi blokları kullanarak oluşturabilirsiniz array:

from pyspark.sql.functions import array, create_map, struct

df.withColumn("some_array", array(lit(1), lit(2), lit(3)))
df.withColumn("some_struct", struct(lit("foo"), lit(1), lit(.3)))
df.withColumn("some_map", create_map(lit("key1"), lit(1), lit("key2"), lit(2)))

Scala'da tam olarak aynı yöntemler kullanılabilir.

import org.apache.spark.sql.functions.{array, lit, map, struct}

df.withColumn("new_column", lit(10))
df.withColumn("map", map(lit("key1"), lit(1), lit("key2"), lit(2)))

Her bir alanda structskullanılmak üzere adlar sağlamak için alias:

df.withColumn(
    "some_struct",
    struct(lit("foo").alias("x"), lit(1).alias("y"), lit(0.3).alias("z"))
 )

veya casttüm nesnede

df.withColumn(
    "some_struct", 
    struct(lit("foo"), lit(1), lit(0.3)).cast("struct<x: string, y: integer, z: double>")
 )

Yavaş da olsa bir UDF kullanmak da mümkündür.

Not :

Aynı yapılar UDF'lere veya SQL işlevlerine sabit argümanlar iletmek için kullanılabilir.


1
Bunu uygulamak için kullanan başkaları için ... withColumn yöntemi, bir sütun ekleyerek veya aynı ada sahip mevcut sütunu değiştirerek yeni bir DataFrame döndürür, bu nedenle sonuçları df'ye yeniden atamanız veya yeni bir değişkene atamanız gerekir. Örneğin, `df = df.withColumn ('new_column', lit (10)) '
Hatta Mien

her yinelemede, sütunun içindeki değerleri değiştirebilir miyiz? bunu zaten denedim for i in range(len(item)) : df.withColumn('new_column', lit({}).format(i)) ama bu işe yaramıyor
Tracy

30

Kıvılcım 2.2'de DataFrame'deki bir sütuna sabit değer eklemenin iki yolu vardır:

1) kullanma lit

2) kullanma typedLit .

İkisi arasındaki fark, typedLitaynı zamanda List, Seq ve Map gibi parametreli skala tiplerini de işleyebilmesidir.

Örnek DataFrame:

val df = spark.createDataFrame(Seq((0,"a"),(1,"b"),(2,"c"))).toDF("id", "col1")

+---+----+
| id|col1|
+---+----+
|  0|   a|
|  1|   b|
+---+----+

1) Kullanarak lit: newcol adlı yeni sütuna sabit dize değeri ekleme:

import org.apache.spark.sql.functions.lit
val newdf = df.withColumn("newcol",lit("myval"))

Sonuç:

+---+----+------+
| id|col1|newcol|
+---+----+------+
|  0|   a| myval|
|  1|   b| myval|
+---+----+------+

2) kullanma typedLit:

import org.apache.spark.sql.functions.typedLit
df.withColumn("newcol", typedLit(("sample", 10, .044)))

Sonuç:

+---+----+-----------------+
| id|col1|           newcol|
+---+----+-----------------+
|  0|   a|[sample,10,0.044]|
|  1|   b|[sample,10,0.044]|
|  2|   c|[sample,10,0.044]|
+---+----+-----------------+

İthalat bildirimi ile birlikte tam sürümü paylaşabilir misiniz
Ayush Vatsyayan

kıvılcım sürüm 2.2.1. import deyimi pyspark.sql.functions adresinden alınmıştır. import typedLit. Ayrıca yukarıda paylaştığınız birini de denedim.
braj
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.