Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

erro no transformar a created date

rodei :
import pyspark.sql.functions as f

df.select(f.explode("created_at")).printSchema() e deu:

DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE] Cannot resolve "explode(created_at)" due to data type mismatch: The first parameter requires the ("ARRAY" or "MAP") type, however "created_at" has the type "STRING". SQLSTATE: 42K09;
'Project [unresolvedalias(explode(created_at#755))]
+- Relation [author_id#753,conversation_id#754,created_at#755,edit_history_tweet_ids#756,id#757,in_reply_to_user_id#758,lang#759,public_metrics#760,text#761] json
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
Daí aqui entendi q era por causa do array o meu é string)
tentei:

df = df.withColumn(

"created_at",

try_to_timestamp("created_at", "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ")

)

df.show()

e veio:
Cell In[24], line 3 1 from pyspark.sql.functions import try_to_timestamp----> 3 df = df.withColumn( 4 "created_at", 5 try_to_timestamp("created_at", "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ") 6 ) 7 df.show()File ~/.local/lib/python3.10/site-packages/pyspark/sql/classic/dataframe.py:1647, in DataFrame.withColumn(self, colName, col) 1642 if not isinstance(col, Column): 1643 raise PySparkTypeError( 1644 errorClass="NOT_COLUMN", 1645 messageParameters={"arg_name": "col", "arg_type": type(col).name}, 1646 )-> 1647 return DataFrame(self._jdf.withColumn(colName, col._jc), self.sparkSession)File ~/.local/lib/python3.10/site-packages/py4j/java_gateway.py:1362, in JavaMember.call(self, *args) 1356 command = proto.CALL_COMMAND_NAME +\ 1357 self.command_header +\ 1358 args_command +\ 1359 proto.END_COMMAND_PART 1361 answer = self.gateway_client.send_command(command)-> 1362 return_value = get_return_value(

...

+- Project [author_id#292, conversation_id#293, to_timestamp(created_at#353, Some(yyyy-MM-dd'T'HH:mm:ss.SSS'Z'), TimestampType, Some(America/Sao_Paulo), true) AS created_at#354, edit_history_tweet_ids#295, id#296, in_reply_to_user_id#297, lang#298, public_metrics#299, text#300] +- Project [author_id#292, conversation_id#293, to_timestamp(created_at#352, Some(yyyy-MM-dd'T'HH:mm:ss.SSS'Z'), TimestampType, Some(America/Sao_Paulo), true) AS created_at#353, edit_history_tweet_ids#295, id#296, in_reply_to_user_id#297, lang#298, public_metrics#299, text#300] +- Project [author_id#292, conversation_id#293, to_timestamp(created_at#294, Some(yyyy-MM-dd'T'HH:mm:ss.SSS'Z'), TimestampType, Some(America/Sao_Paulo), true) AS created_at#352, edit_history_tweet_ids#295, id#296, in_reply_to_user_id#297, lang#298, public_metrics#299, text#300] +- Relation [author_id#292,conversation_id#293,created_at#294,edit_history_tweet_ids#295,id#296,in_reply_to_user_id#297,lang#298,public_metrics#299,text#300] json

Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

2 respostas

Consegui resolver não sei como, tentei isso aqui to_timestamp("created_at", "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'+'0000'") aí deu, daí voltei pro antigo to_timestamp("created_at", "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ") pra testar e deu certo. Vou deixar em aberto porque quero saber o porquê disso, além disso o problema não era spark.stop() nem eu não ter rodar o getOrcreate do spark pq eu tinha dado runAll, mais de uma vez, tentei rodar de todos os jeitos e não tava indo, aí colei esse código to_timestamp("created_at", "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'+'0000'") deu certo, e o outro(yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ) tbm deu certo do nada

solução!

Oi, Guilherme, tudo bem?

Sobre sua dúvida, o comportamento que você observou está relacionado principalmente ao parsing de data do Spark e à forma como ele interpreta o padrão informado no to_timestamp().

Você estava convertendo uma STRING para TIMESTAMP. O padrão:

yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ

usa Z para representar o offset de fuso horário no formato +0000.

Já o padrão:

yyyy-MM-dd'T'HH:mm:ss.SSSSSS'+'0000'

força literalmente a presença do texto +0000.

O que provavelmente aconteceu foi uma destas situações:

  • O número de casas decimais na fração de segundo não correspondia exatamente ao padrão (SSSSSS vs SSSSS)
  • O timezone da sessão (spark.sql.session.timeZone) influenciou a interpretação
  • A coluna foi sobrescrita várias vezes durante os testes, gerando múltiplos Project encadeados no plano lógico

Inclusive, no seu stack trace aparecem vários Project aplicando to_timestamp sucessivamente. Isso indica que a coluna foi sendo transformada várias vezes dentro do mesmo plano.

Quando você testou o formato literal '+'0000', o Spark recompilou o plano e fez o parsing com aquele padrão específico. Ao voltar para o formato com Z, a conversão passou a funcionar porque o plano já estava sendo reconstruído.

Isso não tem relação com spark.stop() nem com getOrCreate, como você mesmo percebeu.

Para evitar esse tipo de comportamento durante testes, recomendo:

  • Não sobrescrever a mesma coluna enquanto estiver testando formatos
  • Criar uma nova coluna para validar o parsing
  • Conferir exatamente como a string está vindo:

df.select("created_at").show(5, truncate=False)

E, se quiser comportamento previsível de timezone:

spark.conf.set("spark.sql.session.timeZone", "UTC")

Em Spark, quando falamos de parsing de datas, uma única diferença no padrão já altera completamente o resultado.

Ótima investigação da sua parte ao testar formatos diferentes. Isso é exatamente o tipo de exploração que ajuda a entender como o Spark realmente funciona. ✨

Espero ter ajudado.

Qualquer dúvida que surgir, compartilhe no fórum. Abraços e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!