दिलचस्प पोस्ट
जावास्क्रिप्ट ऑब्जेक्ट: स्ट्रिंग के रूप में नाम से वैरिएबल प्रॉपर्टी एक्सेस करें क्यों MySQL पूर्ण आउटर पर एक सिंटैक्स त्रुटि की रिपोर्ट करता है? गैर-स्थिर क्षेत्र तक पहुंच नहीं सकते हैं क्वेरीज़ बनाम फ़िल्टर कॉपीराइट उल्लंघन को रोकने के लिए एचटीएमएल, सीएसएस और जावास्क्रिप्ट को एन्क्रिप्ट कैसे करें केवल मानक पुस्तकालय का उपयोग करते हुए गठबंधन मेमोरी आवंटित करने के लिए कैसे? Iframe में सामग्री के लिए CSS ओवरराइड बॉडी स्टाइल? कंस्ट्रक्टर में फ़ील्ड प्रारंभ करना – प्रारंभिक सूची बनाम निर्माता सामग्री कुंजीपटल iPhone-Portrait-NumberPad के लिए टाइप 4 का समर्थन करने वाली कुंजीप्लेन नहीं मिल सकता; 3876877096_Portrait_iPhone-Simple-Pad_Default का उपयोग करते हुए GPS – onActivityResult () को सक्षम करने के लिए LocationSettingsRequest संवाद छोड़ दिया गया XML को शेलस्क्रिप्ट का उपयोग कैसे करें? JEditorPane में एक शब्द हाइलाइट करें क्या जावा में अनाम आंतरिक कक्षाओं को संभव बनाना संभव है? XAMPP – MySQL अप्रत्याशित रूप से बंद क्या “ i` और `? -i` में regex मतलब है?

स्पार्क एसक्यूएल के डाटाफ्रेम में कॉलम के प्रकारों को कैसे बदला जाए?

मान लीजिए मैं ऐसा कुछ कर रहा हूं:

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

लेकिन मैं सचमुच year चाहता था Int (और शायद कुछ अन्य स्तंभों को बदलने)

सबसे अच्छा मैं के साथ आ सकता है है

 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] 

जो थोड़ा जटिल है

मैं आर से आ रहा हूँ, और मुझे लिखने में सक्षम होने के लिए उपयोग किया जाता है, उदा

 df2 <- df %>% mutate(year = year %>% as.integer, make = make %>% toupper) 

मुझे कुछ याद आ रही है, क्योंकि स्पार्क / स्कला में ऐसा करने का एक बेहतर तरीका होना चाहिए …

Solutions Collecting From Web of "स्पार्क एसक्यूएल के डाटाफ्रेम में कॉलम के प्रकारों को कैसे बदला जाए?"

स्पार्क संस्करण 1.4 के बाद से आप कॉलम पर डेटाटाइप के साथ कास्ट विधि लागू कर सकते हैं:

 import org.apache.spark.sql.types.IntegerType val df2 = df.withColumn("yearTmp", df.year.cast(IntegerType)) .drop("year") .withColumnRenamed("yearTmp", "year") 

यदि आप एसक्यूएल अभिव्यक्ति का उपयोग कर रहे हैं तो आप यह भी कर सकते हैं:

 val df2 = df.selectExpr("cast(year as int) year", "make", "model", "comment", "blank") 

अधिक जानकारी के लिए दस्तावेज़ों की जांच करें: http://spark.apache.org/docs/1.6.0/api/scala/#org.apache.spark.sql.DataFrame

[संपादित करें: मार्च 2016: वोटों के लिए धन्यवाद! हालांकि वास्तव में, यह सबसे अच्छा जवाब नहीं है, मुझे लगता है कि withColumn आधार पर समाधान, withColumnRenamed और cast , एमएसएममेलमेन, मार्टिन सेन और अन्य सरल और स्वच्छ हैं]।

मुझे लगता है कि आपका दृष्टिकोण ठीक है, याद रखें कि स्पार्क DataFrame का एक (अपरिवर्तनीय) DataFrame है, इसलिए हम कभी भी एक स्तंभ की जगह नहीं लेते हैं , हर बार एक नई स्कीमा के साथ नए DataFrame बनाते हैं।

मान लें कि आपके पास निम्न स्कीमा के साथ एक मूल डीएफ है:

 scala> df.printSchema root |-- Year: string (nullable = true) |-- Month: string (nullable = true) |-- DayofMonth: string (nullable = true) |-- DayOfWeek: string (nullable = true) |-- DepDelay: string (nullable = true) |-- Distance: string (nullable = true) |-- CRSDepTime: string (nullable = true) 

और कुछ यूडीएफ एक या कई स्तंभों पर परिभाषित है:

 import org.apache.spark.sql.functions._ val toInt = udf[Int, String]( _.toInt) val toDouble = udf[Double, String]( _.toDouble) val toHour = udf((t: String) => "%04d".format(t.toInt).take(2).toInt ) val days_since_nearest_holidays = udf( (year:String, month:String, dayOfMonth:String) => year.toInt + 27 + month.toInt-12 ) 

स्तंभ प्रकारों को बदलने या यहां तक ​​कि दूसरे से एक नया डेटाफ्रेम बनाने जैसे इस प्रकार लिखा जा सकता है:

 val featureDf = df .withColumn("departureDelay", toDouble(df("DepDelay"))) .withColumn("departureHour", toHour(df("CRSDepTime"))) .withColumn("dayOfWeek", toInt(df("DayOfWeek"))) .withColumn("dayOfMonth", toInt(df("DayofMonth"))) .withColumn("month", toInt(df("Month"))) .withColumn("distance", toDouble(df("Distance"))) .withColumn("nearestHoliday", days_since_nearest_holidays( df("Year"), df("Month"), df("DayofMonth")) ) .select("departureDelay", "departureHour", "dayOfWeek", "dayOfMonth", "month", "distance", "nearestHoliday") 

कौन सी पैदावार:

 scala> df.printSchema root |-- departureDelay: double (nullable = true) |-- departureHour: integer (nullable = true) |-- dayOfWeek: integer (nullable = true) |-- dayOfMonth: integer (nullable = true) |-- month: integer (nullable = true) |-- distance: double (nullable = true) |-- nearestHoliday: integer (nullable = true) 

यह आपके अपने समाधान के करीब है बस, प्रकार के परिवर्तन और अन्य परिवर्तनों को अलग udf val रूप में रखने से कोड को अधिक पठनीय और पुन: प्रयोग करने योग्य बनाते हैं।

जैसा cast ऑपरेशन स्पार्क Column लिए उपलब्ध है (और जैसा कि मैं व्यक्तिगत तौर पर इस बिंदु पर @ udf द्वारा प्रस्तावित udf का पक्ष नहीं करता), यह कैसे है:

 df.select( df("year").cast(IntegerType).as("year"), ... ) 

अनुरोधित प्रकार को डालने के लिए? एक स्वच्छ पक्ष प्रभाव के रूप में, उस अर्थ में "मूल्यों" को जाने योग्य / "परिवर्तनीय" नहीं होता, वह null हो जाएगा

यदि आपको इसे एक सहायक विधि के रूप में चाहिए, तो इसका उपयोग करें:

 object DFHelper{ def castColumnTo( df: DataFrame, cn: String, tpe: DataType ) : DataFrame = { df.withColumn( cn, df(cn).cast(tpe) ) } } 

जो इस तरह से प्रयोग किया जाता है:

 import DFHelper._ val df2 = castColumnTo( df, "year", IntegerType ) 

सबसे पहले अगर आप कास्ट करना चाहते हैं

 import org.apache.spark.sql df.withColumn("year", $"year".cast(sql.types.IntegerType)) 

उसी कॉलम के नाम के साथ, कॉलम को एक से बदल दिया जाएगा, आपको जोड़ने और हटाने की आवश्यकता नहीं है।

दूसरा, स्कला बनाम आर। स्कला कोड के बारे में आर के समान है जिसे मैं प्राप्त कर सकता हूं:

 val df2 = df.select( df.columns.map { case year @ "year" => df(year).cast(IntegerType).as(year) case make @ "make" => functions.upper(df(make)).as(make) case other => df(other) }: _* ) 

यद्यपि लंबाई आर की तुलना में थोड़ा अधिक है नोट करें कि mutate आर डेटा फ्रेम के लिए एक फ़ंक्शन है, इसलिए स्काला एक विशेष फ़ंक्शन का उपयोग किए बिना दी गई अभिव्यंजक शक्ति में बहुत अच्छा है।

( df.columns आश्चर्यजनक रूप से ऐरे [स्तंभ] के बजाय एक सरणी [स्ट्रिंग] है, शायद वे चाहते हैं कि यह पायथन पांडा के डेटाफ्रेम की तरह दिखता है।)

आप इसे थोड़ा क्लीनर बनाने के लिए selectExpr का उपयोग कर सकते हैं:

 df.selectExpr("cast(year as int) as year", "upper(make) as make", "model", "comment", "blank") 

वर्ष को स्ट्रिंग से इंट में कनवर्ट करने के लिए, आप निम्न विकल्प को सीएसवी रीडर में जोड़ सकते हैं: "inferSchema" -> "true", देखें डॉटब्रिक्स दस्तावेज़

इसलिए यह केवल वास्तव में काम करता है यदि आपके पास एक jdbc ड्राइवर जैसे sqlserver को सहेजने वाले समस्याएं हैं, लेकिन यह त्रुटियों के लिए वास्तव में मददगार है जो आप सिंटैक्स और प्रकारों के साथ चलेंगे।

 import org.apache.spark.sql.jdbc.{JdbcDialects, JdbcType, JdbcDialect} import org.apache.spark.sql.jdbc.JdbcType val SQLServerDialect = new JdbcDialect { override def canHandle(url: String): Boolean = url.startsWith("jdbc:jtds:sqlserver") || url.contains("sqlserver") override def getJDBCType(dt: DataType): Option[JdbcType] = dt match { case StringType => Some(JdbcType("VARCHAR(5000)", java.sql.Types.VARCHAR)) case BooleanType => Some(JdbcType("BIT(1)", java.sql.Types.BIT)) case IntegerType => Some(JdbcType("INTEGER", java.sql.Types.INTEGER)) case LongType => Some(JdbcType("BIGINT", java.sql.Types.BIGINT)) case DoubleType => Some(JdbcType("DOUBLE PRECISION", java.sql.Types.DOUBLE)) case FloatType => Some(JdbcType("REAL", java.sql.Types.REAL)) case ShortType => Some(JdbcType("INTEGER", java.sql.Types.INTEGER)) case ByteType => Some(JdbcType("INTEGER", java.sql.Types.INTEGER)) case BinaryType => Some(JdbcType("BINARY", java.sql.Types.BINARY)) case TimestampType => Some(JdbcType("DATE", java.sql.Types.DATE)) case DateType => Some(JdbcType("DATE", java.sql.Types.DATE)) // case DecimalType.Fixed(precision, scale) => Some(JdbcType("NUMBER(" + precision + "," + scale + ")", java.sql.Types.NUMERIC)) case t: DecimalType => Some(JdbcType(s"DECIMAL(${t.precision},${t.scale})", java.sql.Types.DECIMAL)) case _ => throw new IllegalArgumentException(s"Don't know how to save ${dt.json} to JDBC") } } JdbcDialects.registerDialect(SQLServerDialect) 

स्ट्रिंग टू इंटिजर में डेटाफ्रेम के डेटाटाइप को संशोधित करने के लिए जावा कोड

 df.withColumn("col_name", df.col("col_name").cast(DataTypes.IntegerType)) 

यह केवल मौजूदा (स्ट्रिंग डेटाटाइप) को पूर्णांक में डाल देगा

 df.select($"long_col".cast(IntegerType).as("int_col")) 

डाली, एफएआईआई का उपयोग करने के सुझाव, चिंगारी 1.4.1 में कास्ट विधि टूटा हुआ है।

उदाहरण के लिए, "8182175552014127960" वाले मान वाले एक स्ट्रिंग कॉलम के साथ एक डेटाफ्रेम को "8182175552014128100" के मान को बड़ा किया गया है

  df.show +-------------------+ | a| +-------------------+ |8182175552014127960| +-------------------+ df.selectExpr("cast(a as bigint) a").show +-------------------+ | a| +-------------------+ |8182175552014128100| +-------------------+ 

हमें इस बग को खोजने से पहले बहुत सारी समस्याओं का सामना करना पड़ा क्योंकि हमारे पास उत्पादन में बड़ा स्तंभ था

यह विधि पुराने कॉलम को छोड़ देगा और समान मूल्यों और नई डेटाटाइप के साथ नए कॉलम बनाएगी। डेटाफ्रेम जब बनाया गया था, तो मेरी मूल डेटाटेप्स थे: –

 root |-- id: integer (nullable = true) |-- flag1: string (nullable = true) |-- flag2: string (nullable = true) |-- name: string (nullable = true) |-- flag3: string (nullable = true) 

इसके बाद मैं डेटाटाइप बदलने के लिए निम्नलिखित कोड चलाया: –

 df=df.withColumnRenamed(<old column name>,<dummy column>) // This was done for both flag1 and flag3 df=df.withColumn(<old column name>,df.col(<dummy column>).cast(<datatype>)).drop(<dummy column>) 

इसके बाद मेरा परिणाम निकला: –

 root |-- id: integer (nullable = true) |-- flag2: string (nullable = true) |-- name: string (nullable = true) |-- flag1: boolean (nullable = true) |-- flag3: boolean (nullable = true) 
  val fact_df = df.select($"data"(30) as "TopicTypeId", $"data"(31) as "TopicId",$"data"(21).cast(FloatType).as( "Data_Value_Std_Err")).rdd //Schema to be applied to the table val fact_schema = (new StructType).add("TopicTypeId", StringType).add("TopicId", StringType).add("Data_Value_Std_Err", FloatType) val fact_table = sqlContext.createDataFrame(fact_df, fact_schema).dropDuplicates() 

स्पार्क एसक्यूएल में कास्ट का उपयोग करके एक कॉलम के डेटा प्रकार को बदल सकता है। तालिका का नाम तालिका है और उसके पास दो कॉलम हैं केवल कॉलम 1 और कॉलम 2 और कॉलम 1 डेटा प्रकार परिवर्तित किया जाना है। ex-spark.sql ("कॉल का चयन करें (डबल 1 के रूप में कॉलम) कॉलम 1 न्यूमेन, टेबल 2 से कॉलम 2") डबल क्लिक करने के स्थान पर अपनी डेटा प्रकार लिखें।