2016-03-17 6 views
6

निम्नलिखित PySpark DataFramePyspark में तिथियों के कॉलम से दिनों के कॉलम को घटाना कैसे?

df = sqlContext.createDataFrame([('2015-01-15', 10), 
           ('2015-02-15', 5)], 
           ('date_col', 'days_col')) 

कैसे दिनों स्तंभ तारीख स्तंभ से घटाया जा सकता को देखते हुए? इस उदाहरण में, परिणामी कॉलम ['2015-01-05', '2015-02-10'] होना चाहिए।

मैंने pyspark.sql.functions.date_sub() में देखा, लेकिन इसके लिए दिनांक कॉलम और एक दिन की आवश्यकता है, यानी date_sub(df['date_col'], 10)। आदर्श रूप में, मैं date_sub(df['date_col'], df['days_col']) करना पसंद करूंगा।

मैं भी एक यूडीएफ बनाने की कोशिश की:

from datetime import timedelta 
def subtract_date(start_date, days_to_subtract): 
    return start_date - timedelta(days_to_subtract) 

subtract_date_udf = udf(subtract_date, DateType()) 
df.withColumn('subtracted_dates', subtract_date_udf(df['date_col'], df['days_col']) 

यह तकनीकी रूप से काम करता है, लेकिन मैं पढ़ा है कि स्पार्क और अजगर के बीच कदम बड़े डेटासेट के लिए प्रदर्शन के मुद्दों पैदा कर सकता है। मैं अभी इस समाधान के साथ रह सकता हूं (समय से पहले अनुकूलित करने की आवश्यकता नहीं है), लेकिन मेरा आंत कहता है कि पाइथन यूडीएफ के बिना इस साधारण चीज़ को करने का एक तरीका बन गया है।

उत्तर

3

मैं selectExpr का उपयोग करके इसे हल करने में सक्षम था।

df.selectExpr('date_sub(date_col, day_col) as subtracted_dates') 

आप मूल DF करने के लिए स्तंभ संलग्न करने के लिए, बस अभिव्यक्ति

df.selectExpr('*', 'date_sub(date_col, day_col) as subtracted_dates') 
+1

यदि आपको एसक्यूएल टाइप करने में कोई फर्क नहीं पड़ता है तो आप वास्तव में इसे 'df.select (expr ("date_sub ({0}, {1})" में सरल बना सकते हैं। प्रारूप ("date_col", "days_col"))' जो बनाता है लिखना तुच्छ है। – zero323

1

नहीं सबसे सुरुचिपूर्ण समाधान कभी लेकिन आप चाल करना चाहिए स्काला में एसक्यूएल भाव हैक करने नहीं चाहते हैं (मुश्किल नहीं है कि यह होना चाहिए, लेकिन इन sql के लिए निजी हैं) कुछ इस तरह:

from pyspark.sql import Column 

def date_sub_(c1: Column, c2: Column) -> Column: 
    return ((c1.cast("timestamp").cast("long") - 60 * 60 * 24 * c2) 
     .cast("timestamp").cast("date")) 

पायथन 2.x के लिए बस ड्रॉप प्रकार एनोटेशन के लिए।

+0

चालाक। मुझे लगता है कि मुझे 'selectExpr' का उपयोग करके थोड़ा अधिक सुरुचिपूर्ण समाधान मिला, लेकिन मदद के लिए धन्यवाद! – kjmij

0

थोड़ा अलग प्रारूप करने के लिए * जोड़ना चाहते हैं, लेकिन यह भी काम करता है:

df.registerTempTable("dfTbl") 

newdf = spark.sql(""" 
        SELECT *, date_sub(d.date_col, d.day_col) AS DateSub 
        FROM dfTbl d 
        """) 
संबंधित मुद्दे