天天看點

Python資料分析script必備知識(1)

作者:蘇沐OvO

1.重定向終端輸出内容

使生成的結果移動到其他位置

# 重定向, 使生成的結果移動到其他位置
import sys

sys.stderr = sys.stdout

print(dir(sys))  # ,,,,,'__stderr__', '__stdin__', '__stdout__',,,,,,

# 使用場景:腳本上線時,想要把輸出結果和錯誤記錄儲存成log,友善檢視。
"""
stdout用于print()和狀态表達式的結果輸出,及input()的瞬時輸出
"""
import sys
# 将目前預設輸出路徑儲存為__str
__stout__ = sys.stdout
# 将後續print輸出結果直接寫入在對應的檔案
sys.stdout = open('log_test.txt','a')

print('輸出結果到log_test.txt檔案裡')

"""
stderr與stdout一樣,用于重定向錯誤至某個檔案

"""
# 将目前的錯誤輸出結果錯誤為__stderr__
__stderr = sys.stderr
# 将後續的報錯資訊寫入對應的檔案中
sys.stderr = open('errorlog.txt','a')
import traceback

try:
    10/0
except:
    traceback.print_exc()           

示圖

Python資料分析script必備知識(1)

2. 擷取目前檔案夾的方法

"""
擷取目前檔案夾的方法
"""

import os

# 擷取目前檔案所在位置的方法
print(os.path.abspath(__file__))
# 擷取目前檔案所在檔案夾的方法
print(os.path.dirname(os.path.abspath(__file__)))
# 拼接路徑,在目前檔案所在檔案夾位置下再加一個test檔案夾
print(os.path.join(os.path.dirname(os.path.abspath(__file__)),'test'))
# 拼接路徑,在目前檔案所在檔案夾位置下再加一個test.py檔案
print(os.path.join(os.path.dirname(os.path.abspath(__file__)),'test.py'))

# 擷取目前檔案名
# 擷取目前檔案的檔案名
print(os.path.basename(os.path.abspath(__file__)))
# 擷取目前檔案所在的檔案夾的檔案名
print(os.path.basename(os.path.dirname(os.path.abspath(__file__))))


# 建立遞歸檔案夾  exist_ok =True 存在就不建立
# 在目前檔案路徑下建立和此腳本平行的檔案夾B
os.makedirs('C',exist_ok=True)

# 擷取目前檔案路徑和檔案所在的檔案夾名
folder_path,file_name = os.path.split(os.path.abspath(__file__))
# 目前檔案夾路徑
print(folder_path)
# 目前檔案名
print(file_name)           

示圖

Python資料分析script必備知識(1)

3.判斷LIST為空的簡便方法

"""
判斷list為空的簡便方法
"""

list1 = [1]
list2 = []

if list1:
    print('list1有資料')

if list2:
    pass
else:
    print('list2沒資料')           

示圖

Python資料分析script必備知識(1)

4.如何用一套腳本執行兩套邏輯

"""
如何用一套腳本執行兩套邏輯
"""

# 如果isONE為True,執行邏輯一;如果isONE為False,執行邏輯二
isONE = True

try:
    if isONE:
        print('執行邏輯一')
    else:
        print('執行邏輯二')
except:
    print('啟動失敗')           

示例:

Python資料分析script必備知識(1)

5.如何用PANDAS修改EXCEL表裡面某一列的值

"""
如何修改pandas某一列的值
"""
import pandas as pd


# 此次需要安裝pandas和xlrd,openpyxk子產品,尤其注意高版本的xlrd子產品依舊支援讀取.xls檔案。
#  安裝pandas包      pip install pandas   # 用0.25.3版本示範
# 網上推薦1.2.0版本   pip install xlrd ==1.2.0   執行此指令安裝不上時,可以嘗試用conda環境
# openpyxl安裝      pip install openpyxl
file_path = r'./demo5.xlsx'
table = pd.read_excel(file_path)
#
# # 方式一
table['測試3'] = '5'
print(table)
print(table['測試3'].dtype)   # object

# 方法二
for i in range(len(table['測試4'])):
    table['測試4'][i] = '6'

print(table['測試4'].dtype)   # int64

# 或者
# for i in range(table.shape[0]):
#     table['測試4'][i] = '6'

# 方法二适合裡面有不同情況,加if時用
file_path = r'demo5.1.xlsx'
table.to_excel(file_path,index=False)           

示圖

Python資料分析script必備知識(1)

6. DATAFRAME數組裡面時間列有0的邏輯轉換

"""
調整pandas裡面是列的時間
"""
import os
import datetime
import pandas as pd

file_path = r'./demo6.xlsx'
a = pd.read_excel(file_path)
print(a)  # 可以看到生産日期這一列有三種格式
print(a['生産日期'].dtype)   # object

for i in range(len(a['生産日期'])):
    # 如果為0,修改為19000101
    if  a['生産日期'][i]== 0:
        a['生産日期'][i] = datetime.datetime.strptime('19000101','%Y%m%d')
    # 如果是8位,轉成時間格式
    elif len(str(a['生産日期'][i])) == 8:
        temp = datetime.datetime.strptime(str(a['生産日期'][i]),'%Y%m%d')
        a['生産日期'][i] = pd.Timestamp(temp)
    # 本來就是%y-%m-%d %h:%m:%s'的,不做處理
    else:
        pass

file_path = r'./demo6.1.xlsx'
if (os.path.exists(file_path)):
    os.remove(file_path)
a.to_excel(file_path,index=False)
print(a['生産日期'].dtype)   # object           

示圖

Python資料分析script必備知識(1)

7.DATAFRAME裡面的時間轉換

"""
時間轉換腳本

strptime  按照特點時間格式将字元串轉換(解析)為時間類型
strftime   将時間格式化,轉字元串

parser.parse 字元串轉成時間格式
"""
import pandas as pd
import datetime
from dateutil import parser

# 列印目前時間
print('列印目前時間:',datetime.datetime.now())
print('列印目前時間類型:',type(datetime.datetime.now()))

# 将目前時間轉成字元串
print('目前時間轉成字元串:',datetime.datetime.now().strftime('%Y%m%d'))
print('檢視目前時間轉成字元串後的類型',type(datetime.datetime.now().strftime('%Y%m%d')))

# 字元串轉時間
a = '2022/12/30'
print('a:',a)
print('a的類型',a)
b = parser.parse(a)
print('b:',b)
print('檢視b的類型',type(b))
print('用時間戳轉a',pd.Timestamp(a))

c = '19000101'
print('用strptime轉成時間類型',datetime.datetime.strptime(c,'%Y%m%d'))

print('擷取目前時間的年月日',datetime.datetime.now().date())
print('擷取目前時間的年',datetime.datetime.now().year)
print('擷取目前時間的月',datetime.datetime.now().month)           

示圖

Python資料分析script必備知識(1)

8. 日期的取整邏輯

"""
日期取整的方式

python timedela() 和 relativedelta()的差別

在挖掘特征時,往往需要按照說幾句段來統計特征,例如最近一個月、最近三個月、最近半年、最近一年  某使用者的行為資料,那麼如何計算篩選這些時間點

1.timedelta()  函數僅支援days和weeks參數
2.relativedelta() 函數可以支援年、月、日、周、時、分、秒參數
"""
import datetime
import pandas as pd

from dateutil.relativedelta import relativedelta

# 目前時間
print(datetime.datetime.now())
# 目前時間加2個月
print(datetime.datetime.now() + relativedelta(months=2))
print('目前時間的字元串形式',datetime.datetime.now().strftime('%Y%m%d'))

# 擷取2022年1月1日到2023年3月1日的時間
start_time = '20220101'
end_time = '20230301'
print(datetime.datetime.strptime(start_time,'%Y%m%d') - datetime.datetime.strptime(end_time,'%Y%m%d'))
# 擷取開始到結束的間隔月份
print(datetime.datetime.strptime(end_time,'%Y%m%d').date() - datetime.datetime.strptime(start_time,'%Y%m%d').date())

# 方法一

start_time = pd.Timestamp(start_time)
for i in range(5):
    start_time = start_time + relativedelta(days=90)
    print('for循環的時間的範圍',start_time)

# 重點:這個5如何确定呢
start_time = '20220101'
start_time_year = datetime.datetime.strptime(start_time,'%Y%m%d').year
start_time_month = datetime.datetime.strptime(start_time,'%Y%m%d').month
end_time = datetime.datetime.strptime(end_time,'%Y%m%d').date()
end_time_year = end_time.year
end_time_month = end_time.month
print(start_time_year,start_time_month,end_time_year,end_time_month)
intermonth = 3
# // 和 / 和 % 均表示的做除法運算
"""
5 / 2  ------> 2.5  正常除
5 // 2 ------> 2    取整
5 % 2  ------> 1     取餘
"""
print('取','3//2',3//2,'2//2',2//2,'1//2',1//2)
if start_time_year == end_time_year:
    number = (end_time_month - start_time_month)  // intermonth
    print('同年間隔',number)
else:
    interyear = end_time_year - start_time_year
    number = (interyear * 12 + (end_time_month - start_time_month)) // intermonth
    print('跨年間隔',number)
# 方法二
start_time = '20220101'
start_time = pd.Timestamp(start_time)
while True:
    start_time = start_time + relativedelta(days=90)
    print('while的時間範圍',start_time)
    if start_time > pd.Timestamp(end_time):
        break           

示圖

Python資料分析script必備知識(1)

9.解壓目前壓縮包下所有檔案

"""
壓縮問題

shutil.copyfilreobj()  将源檔案file-like對象的内容複制到目标file-like對象的方法
"""

import os
import shutil
from zipfile import ZipFile


print('擷取目前檔案路徑',os.path.abspath(__file__))
# 擷取目前檔案路徑 E:\data_analysis\date_analysis_commbat_code\demo9\demo9.py
print('擷取目前檔案的檔案夾名',os.path.dirname(os.path.abspath(__file__)))
# 擷取目前檔案的檔案夾名 E:\data_analysis\date_analysis_commbat_code\demo9
# encode() 原檔案轉二進制
# decode() 二進制轉原文本

def deep_unzip(zip_file):
    """
    遞歸解壓縮并去除目錄層級(平鋪)
    :param zip_file:
    :return:
    """
    with ZipFile(zip_file) as f_zip:
        for zip_file in f_zip.namelist():
            try:
                zip_path_cn = zip_file.encode('cp437').decode('gbk')
            except UnicodeError:
                zip_path_cn = zip_file.encode('utf-8').decode('utf-8')

            filename = os.path.basename(zip_path_cn)
            if not filename:
                continue
            try:
                if filename.endswith('.zip'):
                    deep_unzip(f_zip.open(zip_file))
                else:
                    with open(os.path.join(os.path.dirname(os.path.abspath(__file__)),filename),'wb') as f:
                        shutil.copyfileobj(f_zip.open(zip_file),f)
            except:
                pass

zip_file= r'E:\data_analysis\date_analysis_commbat_code\demo9\testfolder.zip'
deep_unzip(zip_file)           

示圖

Python資料分析script必備知識(1)

10.在PYTHON中定義函數限定格式有用嗎

"""
Python 定義函數示範限定格式有用嗎?

會标黃
不會影響輸出,但是日常習慣得培養,如果繼承關系多了,很難調試
"""
def test(a:str,b:dict):
    print(type(a),type(b))

test(1,2)
test('張三','李四')
test(True,True)
test('1',{})           

示圖

Python資料分析script必備知識(1)

11.PYTHON的傳參技巧

"""
傳參部分

多個參數時,隻想改變個别參數時,可以把其他字段設為預設值,當你傳入新值時,替換掉預設值
"""

def test1(a,b,c,d):
    print(a)

# test1(5)   ypeError: test1() missing 3 required positional arguments: 'b', 'c', and 'd'

def test2(a=None,b=None,c=None,d=2):
    print(a)
test2(5)   # 5           

12.DATAFRAME生成新表的兩種方式(行讀和列替換)

"""
pandas的常見操作(一)

excel分析有兩種方法,一種是行讀,逐行讀取生成新表;另一種是列讀,更換列名即可。
"""
import pandas as pd

table_a = pd.DataFrame([['111','222','3333','4444']]*3,columns=['A','B','C','D'])
print('table_a表為')
print(table_a)


# 張三的資料來源于A的前兩位,李四的資料來源于C的前三位,王五的資料來源于D列的前四位

table_b = pd.DataFrame(columns=['A','B','C'],dtype=object)
# 因為pandas版本問題,可能報AttributeError: type object 'object' has no attribute 'dtype'故加 dtype=object

# 行替換
for i in range(table_a.shape[0]):
    table_b.loc[i] = {'A':table_a['A'][i][:2],
                      'B':table_a['B'][i],
                      'C':table_a['C'][i]}

print('table_b為')
print(table_b)

# 列替換
# 方式一
table_a.rename(columns={'A':'替換a列','B':'替換b列','D':'替換d列'},inplace=True)
print('列替換方式一')
print(table_a)
# 方式二
table_c = table_a.rename(columns={'A':'替換a列','C':'替換c列','D':'替換d列'})
print('列替換方式二')
table_c = table_c[['替換a列','替換c列','替換d列']]
print(table_c)
# 方式三
# 批量列替換
table_a.columns = table_a.columns.str.replace('替換a列','AAA')
print('列替換方式三')
print(table_a)           

示圖

Python資料分析script必備知識(1)

13.必會的時間轉換函數PARSER

"""
pandas異常時間處理函數parser
"""
from dateutil import parser
a_time = '19991231'
print('a_time',parser.parse(a_time))
print('a_time的類型',type(parser.parse(a_time)))
b_time = '1999/12/1'
print('b_time',parser.parse(b_time))
print('b_time的類型',type(parser.parse(b_time)))
c_time = '1999-12-1'
print('c_time',parser.parse(c_time))
print('c_time的類型',type(parser.parse(c_time)))


# 再調用datatime進行加工
from datetime import datetime
a_time1=parser.parse(a_time)
print('對a_time1進行格式化',a_time1.strftime('%Y/%m/%d'))
print('對a_time1進行格式化',a_time1.strftime('%Y/%m/%d %H:%M:%S'))
print('對a_time1進行格式化類型',type(a_time1.strftime('%Y/%m/%d %H:%M:%S')))
b_time1=parser.parse(b_time)
print('對b_time1進行格式化',datetime.strftime(b_time1,'%Y/%m/%d'))
print('對b_time1進行格式化',datetime.strftime(b_time1,'%Y/%m/%d %H:%M:%S'))           

示圖

Python資料分析script必備知識(1)

14.必會的批量處理函數APPLY

"""
pandas的apply()方法是用來調用一個函數,讓此函數對資料對象進行批量處理
    apply可以調用pandas的很多對象,如Datafrma,Series,分組對象,各種時間序列等等。
    apply()使用時,通常放入匿名函數lambda的函數表達式,或一個含作為操作運算。
"""
import numpy as np
import pandas as pd
df1 = pd.DataFrame([[4,9]]*3,columns=['第一列','第二列'])
print('df1')
print(df1)


df2 = df1.apply(np.sum,axis=1)
print('df2,行統計')

print(df2)

# 等價于

df3 = df1.apply(lambda x:np.sum(x),axis=1)
print('df3等價于df2')
print(df3)



df4 = df1.apply(np.sum)
print('df4,預設列統計')
print(df4)

# 等價于
df5 = df1.apply(lambda x:np.sum(x))
print('df5等價于df4')
print(df5)           

示圖

Python資料分析script必備知識(1)

15.當一列資料中,既有時間類型,又有其他類型,如何轉成統一的時間類型?

# 經典案例:某一列中既有時間類型,又有object類型時,如何處理
import pandas as pd
from dateutil import parser
file_path = r'demo15.xlsx'
table = pd.read_excel('demo15.xlsx')
print(table)
print(table['生産日期'].dtypes)

# 編寫一個函數 若為時間格式,不做處理;否則,變成時間格式
def datefortmat(x):
    try:
        # 判斷是否為int類型,如果是,轉成str
        if isinstance(x,int):
            x= str(x)
        result = parser.parse(x)

    except:
        pass
        result = x
    return result

table['生産日期'] = table['生産日期'].apply(datefortmat)
print(table)
print(table['生産日期'].dtypes)           

示圖

Python資料分析script必備知識(1)

16.擷取最新的檔案名并重命名

"""
擷取最新的檔案名并重命名
"""
import os
folder_path = r'E:\data_analysis\date_analysis_commbat_code\demo16'
print(os.listdir(folder_path))

"""
os。path.getmtime()  擷取檔案最後修改時間
os.path.getctime()  擷取檔案最後建立時間
"""
file_path = r'E:\data_analysis\date_analysis_commbat_code\demo16\test1'
print(os.path.getmtime(file_path))
file_path = r'E:\data_analysis\date_analysis_commbat_code\demo16\test2'
print(os.path.getctime(file_path))

# 擷取目前檔案夾的路徑
a = os.path.dirname(os.path.abspath(__file__))
print(a)
# 周遊該目錄下的檔案夾
for i in os.listdir(a):
    print(i)

# 周遊該檔案夾下的每個檔案
find_file = [a + '\\' + i for i in os.listdir(a)]
# 擷取該目錄下最後建立檔案的時間
print(find_file)
for i in find_file:
    print(os.path.getctime(i))

# 選出這四個個檔案中最早建立的檔案
pioneer = max(find_file,key=os.path.getctime)
print(pioneer)
# 選出這四個個檔案中最晚建立的檔案
later = min(find_file,key=os.path.getctime)
print(later)

# 擷取最新修改的檔案
print(max(find_file,key=os.path.getmtime))
# 擷取最後修改的檔案
print(min(find_file,key=os.path.getmtime))

# 把最新修改的檔案換個名字demo_test16.py
need_file = max([a + '\\' + i for i in os.listdir(a)],key=os.path.getmtime)
print('最新修改的檔案',need_file)
print(a)
new_file = os.path.join(a,'test_demo16.py')
os.rename(need_file,new_file)
print(os.listdir(a))           

示例

Python資料分析script必備知識(1)

17 代碼中常見的R和F。(書寫檔案路徑的三種方式)

"""
r和f
"""
# r 主要用在路徑上,保證路徑讀取時不能漏讀
import os

file_path = r'E:\data_analysis\date_analysis_commbat_code\demo16\test17.py'
print(file_path)
# 不加r時還可以兩種方式表示路徑
# 方式一
file_path1 = 'E:\\data_analysis\\date_analysis_commbat_code\\demo16\\test17.py'
print(file_path1)
# 方式二
file_path2 = 'E:/data_analysis/date_analysis_commbat_code/demo16/test17.py'
print(file_path2)
print(os.path.dirname(file_path2))

# f'xxx'的含義:在字元串前加f是把字元串格式化,使可以在字元串中直接使用變量
a = 'Python'
print(f'測試 {a}')           

示圖

Python資料分析script必備知識(1)

18.捕獲異常RAISE。(斷言)

"""
捕獲異常raise

常用的方式
1.單獨raise,該語句引發目前上下文中捕獲的異常,或預設引發RuntimeError異常
2. raise + 異常類名稱: 表示依法執行類型的異常
3.raise + 異常類名稱+ (描述資訊):在引發指定類型的異常的同時,附帶異常的描述資訊
"""

try:
    a = input('請輸入一個數字:')
    # S.isdigit()傳回的是布爾值:True   False
    # S中至少有一個字元且如果S中的所有字元都是數字,那麼傳回結果就是True;否則,就傳回False
    # isalpha() 用于判斷字元串的類型
    if  (not a.isdigit()):
        print('不是數字')
        raise ValueError('a 必須是數字')

except ValueError as e:
    # 除了字元串類型外,使用str還是repr轉換沒有什麼差別。
    # 對于字元串類型,repr轉換後外層會多一對引号,這一特性有時候在eval操作時有用。
    # 指令行下直接輸出對象調用的是對象的repr方法,而print輸出調用的是str方法
   print('引發異常',repr(e))


class PrintError(Exception):
    pass

try:
    a = input('請輸入一個數字:')
    b = a + '11'
    if b != 15:
        raise PrintError('請重新輸入')
except Exception as e:
    print(e)           

示例

Python資料分析script必備知識(1)

19.常見的NOT、AND、OR的優先級問題

"""
not 、and 、or 的優先級問題
優先級:not>and>or
"""
a = True
b = False
c = False
if a and not b and a or b:
    print('為真')

if a or b and c:
    print('為真')

if a and not b:
    print('為真')

# 測試帶括号有效果嗎  ----有
if not a and  b or c :
    print('為真')
else:
    print('為假')

print('&'*30)
if not (a and  b) or c :
    print('為真')
else:
    print('為假')           

示圖

Python資料分析script必備知識(1)

20.删除檔案下所有檔案

"""
删除檔案夾下所有檔案
"""
import os
# 擷取需要删除的檔案夾
print(os.path.join(os.path.dirname(os.path.abspath(__file__)),'test'))

floder_path =os.path.join(os.path.dirname(os.path.abspath(__file__)),'test')

def del_file(path):
    ls = os.listdir(path)
    for i in ls:
        c_path = os.path.join(path,i)
        if os.path.isdir(c_path):  # 如果是檔案夾,遞歸調用
            del_file(c_path)
        else:
            os.remove(c_path)  # 如果是檔案,直接删除
    return

del_file(floder_path)           

示圖

Python資料分析script必備知識(1)