Извлечение года из даты в фрейме данных Pyspark

У меня есть фрейм данных Pyspark, который содержит столбец даты «Сообщенная дата» (тип: строка). Я хотел бы получить счет другого столбца после извлечения года из даты.

Я могу получить счет, если использую строковый столбец даты.

crimeFile_date.groupBy("Reported Date").sum("Offence Count").show()

и я получаю этот вывод

+-------------+------------------+
|Reported Date|sum(Offence Count)|
+-------------+------------------+
|   13/08/2010|               342|
|    6/10/2011|               334|
|   27/11/2011|               269|
|   12/01/2012|               303|
|   22/02/2012|               286|
|   31/07/2012|               276|
|   25/04/2013|               222|
+-------------+------------------+

Чтобы извлечь год из «Сообщенной даты», я преобразовал его в формат даты (используя этот подход) и назвал столбец" Дата ". Однако, когда я пытаюсь использовать тот же код для группировки по новому столбцу и подсчета, я получаю сообщение об ошибке.

crimeFile_date.groupBy(year("Date").alias("year")).sum("Offence Count").show()
TypeError: strptime() argument 1 must be str, not None

Это схема данных:

root
 |-- Offence Count: integer (nullable = true)
 |-- Reported Date: string (nullable = true)
 |-- Date: date (nullable = true)

Есть ли способ исправить эту ошибку? или извлеките год другим методом? Спасибо


person leena    schedule 24.08.2019    source источник


Ответы (1)


Если я правильно понимаю, вы хотите извлечь год из столбца даты String. Конечно, один из способов - использовать регулярное выражение, но иногда он может сбить вашу логику, если регулярное выражение не обрабатывает все сценарии.

вот подход к типу данных даты.

Импорт

import pyspark.sql.functions as f

Создание фрейма данных

l1 = [('13/08/2010',342),('6/10/2011',334),('27/11/2011',269),('12/01/2012',303),('22/02/2012',286),('31/07/2012',276),('25/04/2013',222)]
dfl1 =  spark.createDataFrame(l1).toDF("dates","sum")

dfl1.show()
+----------+---+
|     dates|sum|
+----------+---+
|13/08/2010|342|
| 6/10/2011|334|
|27/11/2011|269|
|12/01/2012|303|
|22/02/2012|286|
|31/07/2012|276|
|25/04/2013|222|
+----------+---+

Теперь вы можете использовать to_timestamp или to_date apis пакета функций

dfl2 = dfl1.withColumn('years',f.year(f.to_timestamp('dates', 'dd/MM/yyyy')))

dfl2.show()
+----------+---+-----+
|     dates|sum|years|
+----------+---+-----+
|13/08/2010|342| 2010|
| 6/10/2011|334| 2011|
|27/11/2011|269| 2011|
|12/01/2012|303| 2012|
|22/02/2012|286| 2012|
|31/07/2012|276| 2012|
|25/04/2013|222| 2013|
+----------+---+-----+

Теперь сгруппируемся по годам.

dfl2.groupBy('years').sum('sum').show()
+-----+--------+                                                                
|years|sum(sum)|
+-----+--------+
| 2013|     222|
| 2012|     865|
| 2010|     342|
| 2011|     603|
+-----+--------+

Отображение в несколько шагов для понимания, но вы можете объединить извлечение года и группировку за один шаг.

С радостью продлю, если вам понадобится другая помощь.

person SMaZ    schedule 25.08.2019
comment
Спасибо за ответ СМАЗ. Я применил его к своему DataFrame, и он вернул результат, аналогичный вашему. Проблема в том, что на выходе отображаются дублированные годы? Я не получаю сумму в год. Это основная цель этого кода. - person leena; 25.08.2019
comment
Вы хотите сохранить исходный столбец даты? или просто сумма за год? - person SMaZ; 25.08.2019
comment
Отлично, рада помочь. Только что отредактировал ответ. Удачного кодирования ..! - person SMaZ; 25.08.2019