Pandalarda tarih saat biçimi nasıl değiştirilir


112

Veri çerçevemde, varsayılan olarak pandas dtype 'nesnesine' dönüştürülen bir DOBsütun (örnek biçim 1/1/2016) var:DOB object

İle tarih formatına bu dönüştürme df['DOB'] = pd.to_datetime(df['DOB']), tarih dönüştürülmüş olur: 2016-01-26ve onun dtypegeçerli: DOB datetime64[ns].

Şimdi bu tarih formatını 01/26/2016diğer genel tarih formatlarına dönüştürmek istiyorum. Nasıl yaparım?

Denediğim yöntem ne olursa olsun, tarihi her zaman 2016-01-26biçiminde gösteriyor.


Yalnızca Jupyter not defteri altında çalışan bir çözüm mü arıyorsunuz? (bu durumda sütun başına bir 'şekillendirici' kullanın) veya düz Python konsolu ve iPython'da çalışır?
smci

Yanıtlar:


215

Diğer biçimlere dt.strftimedönüştürmeniz gerekiyorsa kullanabilirsiniz datetime(ancak bu durumda dtypesütunun object( string) olacağını unutmayın ):

import pandas as pd

df = pd.DataFrame({'DOB': {0: '26/1/2016', 1: '26/1/2016'}})
print (df)
         DOB
0  26/1/2016 
1  26/1/2016

df['DOB'] = pd.to_datetime(df.DOB)
print (df)
         DOB
0 2016-01-26
1 2016-01-26

df['DOB1'] = df['DOB'].dt.strftime('%m/%d/%Y')
print (df)
         DOB        DOB1
0 2016-01-26  01/26/2016
1 2016-01-26  01/26/2016

32
'strftime', DOB1 üzerinde işlemi uygulamak için tarih saat sütununu unicode'a dönüştürür, bunu tekrar tarih saatine dönüştürmemiz gerekir. Data_type'ı kaybetmeden biçimlendirmenin başka bir yolu yok mu?
M.Zaman

1
@jezrael, veri türünü de tutan ve tarihleri ​​bir nesne sütununa döndürmeyen daha iyi bir çözüm var mı? Sorun şu ki, eğer onu çözümde önerildiği gibi 'df [' DOB1 '] = df [' DOB ']. Dt.strftime ('% m /% d /% Y ')' satırından sonra dönüştürmeye çalışırsanız daha sonra tarihler orijinal biçimlerine geri döner.
Outcast

haha, öyleyse bu sütunu .mergebaşka bir veri çerçevesinin bir tarih saat sütununda kullanmak istersem bunu nasıl yapabilirim ? Bunu yapmak için diğer tarih saat sütununu bir nesne sütununa dönüştürmek mantıklı mı .merge?
Outcast

Evet görünüşte Katılıyorum ama ben onun yeni formatını kaybetmeden onun formatını değiştirdikten sonra tarih saat sütun dönüştürmek olamayacağını bana söyledi ":( Değil var" tarafından So.?
Outcast

Tamam, anladığım kadarıyla, .mergeaynı biçime sahip olmasalar bile, her iki sütun da veri saati sütunları ise, yine de doğru şekilde yapılabilir. Bu doğru mu?
Outcast

21

Biçimi değiştirme ancak türü değiştirmeme:

df['date'] = pd.to_datetime(df["date"].dt.strftime('%Y-%m'))

bunu yapmadan önce df ["tarih"] 'in datetime64 olması gerektiğini unutmayın
adhg

4
Hayır! dateSütundaki bazı öğelerin orijinal değerinin " 26 Kasım 2019" olduğunu varsayalım . "zamandan dizge"strftime() anlamına gelir , bu nedenle bu öğe için bir dize olacaktır . Sonra, bu dize dönüştürür geri üzere “Kasım olarak şimdi biçimi, ancak 1 , 2019”! Sonuç şu olacak: Biçim değişikliği yok, tarih değerinin kendisi değişiyor! df["date"].dt.strftime('%Y-%m') "2019-11"pd.to_datetime()datetime64
MarianD

2
@MarianD: Bireysel cevaplarla ilgili tüm yorumlarınız yararlıdır, ancak lütfen bunları cevabınızın alt kısmındaki "Tuzaklar / Bunları yapma" şeklinde özetleyebilir misiniz? Ayrıca, bunların her biriyle ilgili sorunun ne olduğunu açıkça belirtmeniz gerekir: giriş tarihlerinden herhangi biri beklenen formatta değilse, bunlar ya istisnalar atma riskini alır ya da tarihi karıştırır. Sadece "Hayır!" her yer bunu ifade etmez.
smci

8

Aşağıdaki kod, bir öncekinin yerine benim için çalıştı - deneyin!

df['DOB']=pd.to_datetime(df['DOB'].astype(str), format='%m/%d/%Y')

2
Hayır! Kişisel format='%m/%d/%Y'parametre içindir ayrıştırma , bir dize sen gerekiyor yani böyle bir formatta dize sağlamak için (örneğin "5/13/2019"). Daha fazlası yok, format değişikliği yok. Halen - şeklinde görüntülenecektir 2019-05-13veya df['DOB'].astype(str)böyle bir formatta olmayan öğe (ler) içeriyorsa, örneğin bir formatta bir istisna oluşturacaktır "2019-05-13".
MarianD

5

İlk cevapla karşılaştırıldığında, önce dt.strftime (), sonra pd.to_datetime () kullanmanızı tavsiye edeceğim. Bu şekilde, yine de datetime veri türü ile sonuçlanacaktır.

Örneğin,

import pandas as pd

df = pd.DataFrame({'DOB': {0: '26/1/2016 ', 1: '26/1/2016 '})
print(df.dtypes)

df['DOB1'] = df['DOB'].dt.strftime('%m/%d/%Y')
print(df.dtypes)

df['DOB1'] = pd.to_datetime(df['DOB1'])
print(df.dtypes)

2
Bu en azından benim durumumda çalışmıyor. Özellikle, sütun tarih saat veri türüne dönüştürülür, ancak değerler de orijinal biçime dönüştürülür!
Outcast

Hayır! Sözdizimi hatası (eksik ayraç), Pandas sürümümde (0.25.1) başka bir sözdizimi hatası (dt.strftime () - sadece .dt erişimcisini datetim benzeri değerlerle kullanabilir) - doğal veri türüne güveniyorsunuz, ancak farklı sürümlerde Pandalar, doğal veri türleri farklı olabilir) ve garip bir mantık - neden datetime'ı dizeye ve sonra tekrar tarih saatine dönüştürelim ? Rishi Jain'in cevabına yaptığım yorumu görün.
MarianD

2

Bunu deneyebilirsiniz, tarih biçimini GG-AA-YYYY'ye dönüştürecektir:

df['DOB'] = pd.to_datetime(df['DOB'], dayfirst = True)

Hayır! dayfirst=Trueyalnızca bir tarih ayrıştırma sırasının belirtimidir, örneğin, "2-1-2019" olarak kararsız tarih dizesi 1 Şubat 2019 olarak değil 2 Ocak 2019 olarak ayrıştırılacaktır. Daha fazla bir şey yok, çıktı biçimlendirmesinde değişiklik yok .
MarianD

2

Arasında bir fark var

  • İçerik bir dataframe hücrenin (bir ikili değer) ve
  • onun sunum , bizim için insanları (görüntülemeden).

Yani soru şu: Veri / veri türlerini değiştirmeden verilerimin uygun sunumuna nasıl ulaşabilirim ?

İşte cevap:

  • Veri çerçevenizi görüntülemek için Jupyter not defterini kullanıyorsanız veya
  • Bir HTML dosyası biçiminde bir sunuya ulaşmak istiyorsanız (çok sayıda hazırlanmış gereksiz idve daha fazla CSS stili classiçin özniteliklerle bile - bunları kullanabilir veya kullanmayabilirsiniz),

stil kullanın . Stil, veri çerçevenizin veri / veri türlerini değiştirmez.

Şimdi size Jupyter not defterinde nasıl ulaşacağınızı göstereceğim - HTML dosyası biçiminde bir sunum için sorunun sonundaki nota bakın.

Sütununun DOB zaten türüne sahipdatetime64 olduğunu varsayacağım (ona nasıl ulaşacağını bildiğini gösterdin). Size bazı temel stilleri göstermek için basit bir veri çerçevesi (yalnızca bir sütun içeren) hazırladım:

  • Tarzlı değil:

       df
          DOB
0  2019-07-03
1  2019-08-03
2  2019-09-03
3  2019-10-03
  • Biçimlendirme mm/dd/yyyy:

       df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})
          DOB
0  07/03/2019
1  08/03/2019
2  09/03/2019
3  10/03/2019
  • Biçimlendirme dd-mm-yyyy:

       df.style.format({"DOB": lambda t: t.strftime("%d-%m-%Y")}) 
          DOB
0  03-07-2019
1  03-08-2019
2  03-09-2019
3  03-10-2019

Dikkatli ol!
Dönen nesne bir veri çerçevesi DEĞİLDİR - bu sınıfın bir nesnesidir Styler, bu nedenle şuna geri atamayın df:

Bunu yapma:

df = df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})    # Don´t do this!

(Her veri çerçevesinin kendi .styleözelliği tarafından erişilebilen Styler nesnesi vardır ve bu df.stylenesneyi veri çerçevesinin kendisini değil, değiştirdik .)


Sorular ve cevaplar:

  • S: Bir Jupyter not defteri hücresinde son komut olarak kullanılan Styler nesneniz (veya onu döndüren bir ifade) neden Styler nesnesinin kendisini değil de (stilize edilmiş) tablonuzu görüntülüyor ?

  • C: Çünkü her Styler nesnesinin, ._repr_html_()veri çerçevenizi oluşturmak için bir HTML kodu döndüren bir geri çağırma yöntemi vardır (güzel bir HTML tablosu olarak).

    Jupyter Notebook IDE , ona sahip olan nesneleri oluşturmak için bu yöntemi otomatik olarak çağırır .


Not:

Stil için Jupyter not defterine ihtiyacınız yok (yani , veri / veri türlerini değiştirmeden bir veri çerçevesini güzel bir şekilde çıkarmak için ).

render()HTML koduyla bir dize elde etmek istiyorsanız (ör. Biçimlendirilmiş veri çerçevenizi Web'de yayınlamak veya tablonuzu HTML biçiminde sunmak için) bir Styler nesnesinin de bir yöntemi vardır :

df_styler = df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})
HTML_string = df_styler.render()

Bunun gibi şekillendirici kodun altında çalıştırılmak üzere tasarlandığını ve yalnızca Jupyter dizüstü bilgisayar altında etkili olduğunu ve konsolda veya iPython'da çalıştırıldığında kesinlikle sıfır etkiye sahip olduğunu belirtmek gerekir . OP, "Jupyter altında" belirtmedi, bu nedenle bu, kurulumlarına bağlı olarak uygun bir çözüm olabilir veya olmayabilir. Birçok veri bilimi kodu kopyalanıp yapıştırılır ve Jupyter'e özgü varsayımlar açıkça belirtilmez, sonra insanlar (konsol) ortamlarında çalıştırıldığında şekillendirici kodunun neden "çalışmadığını" merak ederler.
smci

@smci, cevabımın ikinci paragrafında açıkça belirtilmiyor mu? Koşullu if, ifade her programcı tarafından çok biliniyor mu? - Yorumunuz için teşekkürler, ancak bazı insanlar için faydalı olabilir.
MarianD

hayır bu çok belirsiz, ayrıca gömülü. Orijinal soru Jupyter hakkında hiçbir şey varsaymıyordu ve OP ve bazı kullanıcılar Jupyter'e sahip olmayabilir. Cevabınız, ilk satırında kalın harflerle "Aşağıdaki yaklaşım (stil) yalnızca Jupyter dizüstü bilgisayar altında çalışır ve Jupyter not defterinin dışında çalıştırıldığında hiçbir etkisi olmayacaktır" demeniz gerekir . (Veri bilimi bloglarında ve sitelerinde, günlük olarak insanların Jupyter kodunu Jupyter dışı ortamlara gönderdiğini ve neden çalışmadığını merak ettiğini görüyorum).
smci

Güzel. Ayrıca, diğer "strftime-ile-dizgeye-sonra-tekrar-pd.to_datetime-ile-tekrar-dön" yaklaşımlarında tanımladığınız tüm (birçok) tuzağı eklemenizi öneririm. En azından istisnaları yükseltmek ve yakalamaktan bahsetmek gerekir. Ayrıca, ne kadar kesin ve istisnai durumdan memnun olduğunu ve geçersiz çıktıların zorlanıp zorlanmayacağını veya neye zorlanacağını kontrol pd.to_datetime()edecek argümanlara sahiptir . "Gerçek dünya" veri kümelerinde onu daha karmaşık kılan şey, karışık / eksik / eksik biçimler, zamanlar, saat dilimleri vb. istisnalar mutlaka kötü şeyler değildir. errors='raise'/'coerce'/'ignore', dayfirst, yearfirst, utc, exactNaT
smci

... ya da bunu Jupyter dışı yaklaşımlardaki tuzaklar toplamı olarak yazabilirim.
smci

1

Aşağıdaki kod, 'tarih saat' türünde değişir ve ayrıca verilen biçim dizesindeki biçimler. İyi çalışıyor!

df['DOB']=pd.to_datetime(df['DOB'].dt.strftime('%m/%d/%Y'))

2
şu şekilde değiştirin:df['DOB']=pd.to_datetime(df['DOB']).dt.strftime('%m/%d/%Y')
John Doe

Hayır! - Neden tarih saati dizeye ve ardından tarih saatine dönüştürülsün ? Diğer cevaplara verdiğim yorumları gör.
MarianD
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.