Spark DataFrame में एक स्थिर कॉलम कैसे जोड़ें?


137

मैं DataFrameकुछ मनमाने मूल्य (जो प्रत्येक पंक्ति के लिए समान है) के साथ एक कॉलम जोड़ना चाहता हूं । जब मैं withColumnनिम्नानुसार एक त्रुटि प्राप्त करता हूं :

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'

ऐसा लगता है कि मैं फ़ंक्शन को अन्य कॉलमों में से एक को जोड़कर और घटाकर काम करने में ट्रिक कर सकता हूं (इसलिए वे शून्य में जोड़ते हैं) और फिर मुझे इच्छित संख्या जोड़ना (इस मामले में 10):

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)]

यह सर्वोच्च हैक है, है ना? मुझे लगता है कि ऐसा करने का एक अधिक कानूनी तरीका है?

जवाबों:


221

स्पार्क 2.2+

2.2 प्रस्तुत किया स्पार्क typedLitका समर्थन करने के Seq, Mapऔर Tuples( चिंगारी से 19,254 ) और निम्न कॉल समर्थन किया जाना चाहिए (स्काला):

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)))

स्पार्क 1.3+ ( lit), 1.4 + ( array, struct), 2.0+ ( map):

इसके लिए दूसरा तर्क DataFrame.withColumnहोना चाहिए Columnताकि आपको शाब्दिक प्रयोग करना पड़े:

from pyspark.sql.functions import lit

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

यदि आपको जटिल स्तंभों की आवश्यकता है, तो आप इन ब्लॉकों का उपयोग करके बना सकते हैं जैसे 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)))

बिल्कुल वैसा ही तरीका स्काला में इस्तेमाल किया जा सकता है।

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)))

प्रत्येक क्षेत्र पर structsउपयोग के लिए नाम प्रदान करने के लिए alias:

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

या castपूरी वस्तु पर

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

यह भी संभव है, हालांकि धीमी, एक यूडीएफ का उपयोग करने के लिए।

नोट :

यूडीएफ या एसक्यूएल कार्यों के लिए निरंतर तर्क पारित करने के लिए एक ही निर्माण का उपयोग किया जा सकता है।


1
इसे लागू करने वाले अन्य लोगों के लिए ... withColumn पद्धति एक कॉलम जोड़कर या उसी नाम वाले मौजूदा कॉलम को प्रतिस्थापित करके एक नया DataFrame लौटाती है, इसलिए आपको परिणामों को df या नए चर पर असाइन करने के लिए फिर से असाइन करना होगा। उदाहरण के लिए, `df = df.withColumn ('new_column', lit (10)) '
Even Mien

हर पुनरावृत्ति के साथ, क्या हम कॉलम के अंदर मान बदल सकते हैं? मैं पहले से ही यह कोशिश की है, for i in range(len(item)) : df.withColumn('new_column', lit({}).format(i)) लेकिन यह काम नहीं करता है
ट्रेसी

30

स्पार्क 2.2 में डेटाफ़्रेम में एक कॉलम में निरंतर मूल्य जोड़ने के दो तरीके हैं:

1) का उपयोग करना lit

२) उपयोग करना typedLit

दोनों के बीच का अंतर यह है कि typedLitपैरामीटर स्कैला प्रकार जैसे लिस्ट, Seq और मैप को भी हैंडल कर सकते हैं

नमूना डेटा नाम:

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

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

1) का उपयोग करना lit: newcol नामक नए कॉलम में निरंतर स्ट्रिंग मान जोड़ना:

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

परिणाम:

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

2) का उपयोग कर typedLit:

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

परिणाम:

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

क्या आप आयात विवरण के साथ पूरा संस्करण साझा कर सकते हैं
आयुष वात्स्यायन

स्पार्क संस्करण 2.2.1। आयात विवरण pyspark.sql.functions आयात typedLit से है। ऊपर आपके द्वारा साझा की गई कोशिश भी।
ब्रज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.