python命令行參數,[轉載] 整理總結 python 中時間日期類數據處理與類型轉換(含 pandas)

 2023-11-19 阅读 31 评论 0

摘要:參考鏈接: Python中的時間函數 2(日期操作) 我自學 python 編程并付諸實戰,迄今三個月。 pandas可能是我最高頻使用的庫,基于它的易學、實用,我也非常建議朋友們去嘗試它。——尤其當你本身不是程序員,但多少跟表格或數據打點交道時࿰

參考鏈接: Python中的時間函數 2(日期操作)

我自學 python 編程并付諸實戰,迄今三個月。 pandas可能是我最高頻使用的庫,基于它的易學、實用,我也非常建議朋友們去嘗試它。——尤其當你本身不是程序員,但多少跟表格或數據打點交道時,pandas 比 excel 的 VBA 簡單優雅多了。?

pandas 善于處理表格類數據,而我日常接觸的數據天然帶有時間日期屬性,比如用戶行為日志、爬蟲爬取到的內容文本等。于是,使用 pandas 也就意味著相當頻繁地與時間日期數據打交道。這篇筆記將從我的實戰經驗出發,整理我常用的時間日期類數據處理、類型轉換的方法。?

python命令行參數。與此相關的三個庫如下。?

?

import time

import datetime

python整理excel數據,import pandas as pd

?

?

其中,time 和datetime都是 python 自帶的,pandas則是一個第三方庫。換言之,前兩者無需額外安裝,第三方庫則需要通過pip install pandas命令行自行安裝。如何檢查自己是否安裝了某個庫,如何安裝它,又如何查看和更新版本,對新手來說是一個比較大的話題,也是基礎技能,值得另外整理一篇筆記,就不在這里占篇幅了。當然,如果你不想自己本地折騰,也可電腦瀏覽器訪問https://xue.cn 這樣的網站,網頁上直接寫代碼并運行它們。?

python重點?一、time模塊?

對time模塊,我最常用到的功能就三個:?

指定程序休眠;獲取當前時間戳;時間戳與本地時間的互相轉換?

time.sleep(s) 指定程序休眠 s 秒?

python應用。指定程序休眠時間,通常是在長時間運行的循環任務中進行。比如爬蟲任務,控制讀取網頁的時間間隔;自循環任務的時間間隔,調用瀏覽器打開網頁的時間間隔等等。?

先用兩個打印語句,輔助觀察和理解time.sleep()的效果:?

print(datetime.datetime.now())

time.sleep(5)

python處理數據,print(datetime.datetime.now())

?

至于長時間運行的循環任務,我通常是把核心業務邏輯封裝好,利用jupyter lab自帶的多進程特定,建一個 notebook 放入下面這個函數去持續運行。?

?

python和java?def repeat_myself(how_many_times = 10):

? ? print('--------',how_many_times,'----------')

? ? # 被封裝的核心代碼

? ? your_main_def()?

爬蟲python,?

? ? # 自循環減 1 ;如果剩余次數是0,則終止自循環

? ? how_many_times += -1

? ? if how_many_times == 0:

python date。? ? ? ? print(datetime.datetime.now(),'stop it.')

? ? ? ? return

?

? ? # 每次調用設定一個時間間隔

python 庫。? ? print(datetime.datetime.now(),'have a rest')

? ? how_long = random.randint(30,120)

? ? time.sleep(how_long)

? ? return repeat_myself(how_many_times)

?

repeat_myself(12)

?

?

time.time()獲取當前時間戳?

最初我認為無需急于掌握時間戳這個技能點,但實戰中,1) 我的爬蟲有時爬取到時間戳類型的數據,為了易讀,要把它轉換為正常人能看懂的方式;2) 使用 mysql 時我關心存儲所占用的空間以及讀寫效率,并獲知一個時間數據存成 char 不如時間戳更節省空間。好吧,實戰需要,那么趕緊掌握起這個小技能吧。?

先了解下如何生成時間戳。通過time.time()得到的時間戳,是一個有著10位整數位 + 6位小數位的浮點數,可根據需要簡單運算轉換為需要的 10、13、16 位整數時間戳。?

# 獲取當前時間戳

?

# 值是 1569642653.1041737 ,float

a = time.time()

# 1569642653,得到 10位時間戳,int

b = int(a)

# 1569642653104,得到 13位時間戳,int

c = int(a * 1000)

# 1569642653104173,得到 16位時間戳,int

d = int(a * 1000000)

?

?

接下來,了解一下時間戳和人類易讀的時間之間的轉換。?

時間戳與人類易讀的時間互相轉換?

如上面所示,時間戳是一個float或int類型的數值,至少有 10 位整數。把時間戳轉換為人類易讀的時間,用到的是localtime(),與其相反的是mktime()能把人類易讀的時間轉換為時間戳。?

?

# 時間戳轉換為人類易讀的時間

# 結果是:time.struct_time(tm_year=2019, tm_mon=9, tm_mday=28, tm_hour=12, tm_min=12, tm_sec=1, tm_wday=5, tm_yday=271, tm_isdst=0)

# 數據類型是 time.struct_time

e = time.localtime(a)

f = time.localtime(b)

g = time.localtime(c//1000)

h = time.localtime(d//1000000)

?

# 人類易讀的時間轉換為時間戳

# 結果是:1569643921.0,float

i = time.mktime(e)

j = time.mktime(f)

k = time.mktime(g)

l = time.mktime(h)

?

?

經type()檢查,localtime() 得到的結果,是 time.struct_time 類型,直觀可見這個類型對人類依然不是最友好的。最友好的表達將用到 strftime 和 strptime 這兩個方法,處理 time.struct_time 與string字符串 兩個類型的互換。?

?

# 把 struct_time 轉換為指定格式的字符串

# '2019-09-28 12:12:01 Saturday'

good = time.strftime("%Y-%m-%d %H:%M:%S %A", e)

?

# 把字符串轉換為 struct_time

# 結果是:time.struct_time(tm_year=2019, tm_mon=9, tm_mday=28, tm_hour=12, tm_min=12, tm_sec=1, tm_wday=5, tm_yday=271, tm_isdst=-1)

nice = time.strptime(good,"%Y-%m-%d %H:%M:%S %A")

?

?

在我的筆記中,僅整理總結自己常用的方法,至于我自己從未用到或很少用到的方法,并不羅列其中。如有小伙伴希望系統完整地了解,可直接搜:time site:python.org 或點擊訪問官方文檔 能查看完整說明。?

二、datetime 模塊?

datetime獲取到的時間數據是非常易讀的,在和人交互時,比 time 更好用一些。我通常把 datetime 用于以下 2 個場景。?

場景A:log時間戳,打印信息監控代碼運行情況?

新手寫代碼,變相就是寫bug,以我自己來說,使用不熟模塊或寫新業務時,寫代碼和調試修復錯誤,占用時間常常各半。采用 jupter lab的 notebook,讓寫代碼和調試方便許多,但依然需要 print() 打印信息方便監控代碼運行情況。比如下方這個代碼片段:?

# 顯示效果:2019-09-28 12:44:36.574576 df_rlt ...

print(datetime.datetime.now(),'df_rlt ...')

for one in df_rlt.values:

? ? print(datetime.datetime.now(),one,'for circle ...')

? ? try:

? ? ? ? sql_insert = 'INSERT INTO questions(q_id,q_title,q_description,q_keywords,q_people,q_pageview,time) VALUES( "'\

? ? ? ? ? ? + str(quesition_id) + '", "' + str(one[0])+ '", "' + str(one[1]) + '", "' + str(one[2]) + '", "' \

? ? ? ? ? ? + str(one[3]) + '", "' + str(one[4]) + '", "' + str(datetime.datetime.now()) + '");'?

? ? ? ? sql_update = 'update topic_monitor SET is_title="1" where question_id = "' + str(quesition_id) + '";'

? ? ? ? cursor.execute(sql_insert)

? ? ? ? cursor.execute(sql_update)

? ? ? ? conn.commit()

? ? ? ? print(datetime.datetime.now(),'sql_insert ...')

? ? except:

? ? ? ? print(datetime.datetime.now(),'sql_insert error...')

? ? ? ? continue

?

?

場景B:文件名時間戳,文件名中增加當前日期?

文件名中增加當前日期作為參數,既避免文件相互覆蓋(比如數據每天更新,每天導出一次),也方便直觀地查看文件版本。當然啦,如果處理的是超級頻繁導出的文件,精確到天并不滿足需求,可自行精確到時分秒,或直接用int(time.time())時間戳作為文件名中的參數。?

# 效果:'d:/out_put/xuecn_comments_statistics_2019-09-28.xlsx'

comms_file = output_path + 'xuecn_comments_statistics_' + str(datetime.datetime.now())[:10] + '.xlsx'

?

直接搜:datetime site:python.org 或者點擊訪問 python 官方文檔查看超多方法說明。?

與官方文檔對比,我已經用到的知識點真是九牛一毛。不過也沒關系,從需要和興趣出發就好,沒必要硬著頭皮把自己打造成移動字典,很多方法呢都是用多了自然記住了,無需反復死記硬背。?

三、pandas 中的時間處理?

我寫這篇筆記,本就是奔著精進 pandas 來的,前面花了很大篇幅先整理了time和datetime這些基礎功,現在進入重頭戲,即 pandas 中與時間相關的時間處理。?

前面兩個部分舉例,處理的均是單個值,而在處理 pandas 的 dataframe 數據類型時,事情會復雜一點,但不會復雜太多。我在實戰中遇到的情況,總結起來無非兩類:?

數據類型的互換索引與列的互換?

需要留意的是,數據類型應該靠程序判斷,而非我們人肉判斷。python pandas 判斷數據類型,常用type() 和 df.info() 這兩個方法。?

首先,我們構造一個簡單的數據示例 df?

構造這個實例,只是為了方便后面的展開。構造一個 dataframe 的方法有非常多。這里就不展開了。?

import random

df = pd.DataFrame({

? ? 'some_data' : [random.randint(100,999) for i in range(1,10)],

? ? 'a_col' : '2019-07-12',

? ? 'b_col' : datetime.datetime.now().date(),

? ? 'c_col' : time.time()},

? ? index=range(1,10))

?

?

然后,我們逐項查看它的數據類型?

剛學著用pandas經常會因為想當然地認為某個對象是某個數據類型,從而代碼運行報錯。后來學乖,特別留心數據類型。?

某個數據是什么類型,如何查看,某個方法對數據類型有什么要求,如何轉換數據類型,這些都是實戰中特別關心的。?

# pandas.core.frame.DataFrame

type(df)

# pandas.core.series.Series

type(df['some_data'])

# numpy.ndarray

type(df['some_data'].values)

# numpy.int64

type(df['some_data'].values[0])

# str

type(df['a_col'].values[0])

# datetime.date

type(df['b_col'].values[0])

# numpy.float64

type(df['c_col'].values[0])

?

df.info()

"""

<class 'pandas.core.frame.DataFrame'>

RangeIndex: 9 entries, 1 to 9

Data columns (total 4 columns):

some_data? ? 9 non-null int64

a_col? ? ? ? 9 non-null object

b_col? ? ? ? 9 non-null object

c_col? ? ? ? 9 non-null float64

dtypes: float64(1), int64(1), object(2)

memory usage: 420.0+ bytes

"""

?

?

為什么要轉換數據類型,有什么用途?

為什么要把時間日期之類的數據轉換為 pandas 自帶的 datetime64 類型呢?這當然不是強迫癥整潔癖,而且即便不做轉換也不會帶來任何報錯。?

最重要的原因是,數據分析將會高頻用到基于時間的統計,比如:每天有多少用戶注冊、登錄、付費、留言……產品運營通常按日統計,把dt.date改成dt.week、dt.month、dt.hour就能輸出周統計、月統計、分時統計……當然官方文檔介紹的方法還有更多,我提到的僅是自己高頻使用的方法。?

?

df.groupby(df['c_col'].dt.date).some_data.agg('sum')

?

?

次要的原因是,輸出數據到 excel 表格中發給其它同事時,咱們還是得考慮文件的易讀、簡潔吖。比如,時間戳得轉換為人能看懂的文本,比如僅顯示日期,無需把后面時分秒之類的冗余數據也顯示出來等等。?

通過不同方式拿到的數據類型,通常相互之間并不一致,而我們想要使用某些方法提高生產力,必須遵循該方法所要求的數據類型。于是數據類型轉換就成了剛需。?

如何轉換為 pandas 自帶的 datetime 類型?

在上方示例中,肉眼可見 a_col、b_col 這兩列都是日期,但 a_col 的值其實是string 字符串類型,b_col的值是datatime.date類型。想要用pandas 的按時間屬性分組的方法,前提是轉換為 pandas 自己的 datetime類型。?

轉換方法是一致的:?

# 字符串類型轉換為 datetime64[ns] 類型

df['a_col'] = pd.to_datetime(df['a_col'])

# datetime.date 類型轉換為 datetime64[ns] 類型

df['b_col'] = pd.to_datetime(df['b_col'])

# 時間戳(float) 類型轉換為 datetime64[ns] 類型

df['c_col'] = pd.to_datetime(df['c_col'].apply(lambda x:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(x))))

?

# 查看轉換后的屬性

df.info()

"""

<class 'pandas.core.frame.DataFrame'>

RangeIndex: 9 entries, 1 to 9

Data columns (total 4 columns):

some_data? ? 9 non-null int64

a_col? ? ? ? 9 non-null datetime64[ns]

b_col? ? ? ? 9 non-null datetime64[ns]

c_col? ? ? ? 9 non-null datetime64[ns]

dtypes: datetime64[ns](3), int64(1)

memory usage: 420.0 bytes

"""

?

?

其中,難點是 c_col 這列。其實不難,只是幾個嵌套,顯得有點復雜而已:?

y = time.localtime(x),把 x 從時間戳(10個整數位+6個小數位的那串數字)類型轉換為struct_timez = time.strftime('%Y-%m-%d %H:%M:%S',y) 把上一步得到的 struct_time 轉換為 字符串lambda x:z 匿名函數,輸入一個值x,得到字符串zdf['c_col'].apply() 對整列每個值做上述匿名函數所定義的運算,完成后整列值都是字符串類型pd.to_datetime() 把整列字符串轉換為 pandas 的 datetime 類型,再重新賦值給該列(相當于更新該列)?

我其實非常希望有個過來人告訴我,這個知識點用的頻繁嗎,在什么時期是否應該掌握?于是我自己寫的筆記,通常都會留意分享自己實戰過來的這個判斷。當然啦,每個人實戰的方向不太一樣,大家可作參考,無需完全照搬。具體說來:?

第 1、2 步是第一部分 time 模塊總結到基礎技能。第 3 步的匿名函數 lambda 是相當風騷的知識點,xue.cn 《自學是門手藝》有一節專門講到它,建議掌握。第 4 步結合匿名函數lambda,是對 dataframe 整列進行統一操作的重要技能點,多用幾次就熟練了。第 5 步 無需死記硬背。為啥我總說 pandas 易學好用呢?因為它的很多方法,都能直接見文生義,幾乎沒有記憶負擔。?

關于時間日期處理的pandas 官方文檔篇幅也挺長的,沒中文版,大家想要系統了解,直接點開查閱吧~?

關于索引與列的互換?

不管何種原因導致,通常使用 pandas 時會經常對索引與列進行互換。比如把某列時間數據設為索引,把時間索引設為一列……這些操作并沒有額外的特別之處,都統一在pandas 如何進行索引與列的互換 這個技能點之下。限于篇幅,我這里就不展開啦。不過索引與列的轉換是高頻操作,值得另寫一篇筆記。?

有一點反復強調都不過為,即,我的筆記僅記錄自己實戰中頻繁遇到的知識技能,并非該模塊全貌。如需系統掌握或遇到筆記之外的疑問,請善用搜索技能喲:你的關鍵詞們 site:python.org。?

如果我的整理帶給你幫助,請點個贊鼓勵我繼續分享。如需勘誤請留言,或挪步到我的 github 提issues。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/181243.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息