天天看點

Pandas 批量處理文本表

批量處理文本表, 計算字段, 索引 loc, 列轉行索引 set_index( ) , 跳過行數 skiprows(), 指定列名 columns 等基本操作, 就能完成很多事情

就是一個批量讀取檔案, 然後計算名額的過程. 難度到是沒啥, 隻是想記錄一把, 畢竟這類的需求, 其實還是蠻多的.

但涉及一些資料的安全, 和名額這塊也是不能透露的, 是以隻能是貼上代碼, 目的還是給自己以後做參考的. 代碼中有個常數, 其實表示每個檔案, 每行的同位置的值, 是一樣的. 是發現規律了, 最開始是找近似, 去最為接近的一條, 後來寫完發現, 根本不用不動. 然後, 文本資料, 就是字尾不是常用的, Excel, Csv.. 這種, 給我有個 xx.sed 從未見過的這類. 還好我基本功可以, 畢竟當年抄過書本, read_table 這類的騷操作, 就恰好滿足需求了.

因為涉及的資料不能公開, 業務這塊也不能談及, 名額計算比較多和雜. 總之是給我自己看的, 并未作為分享的.

from os import listdir
import pandas as pd
from math import log10
import time

# 發現資料規律, 每個檔案的第一列值 Wvl 都是固定的, 直接取即可
# 每個名額值行索引(Wvl)可以先全部找出來
R990 = 990.4
R720 = 719.5
R860 = 860.2
R790 = 789.7
R670 = 669.4
R730 = 730.2
R525 = 525.2
R750 = 749.9
R705 = 704.8
R445 = 444.5
R550 = 550.1
R870 = 869.5
R680 = 680.3
R810 = 809.7
R800 = 799.7
R700 = 699.4
R840 = 840.1
R1510 = 1511.8
R1680 = 1681.2

start = time.time()

ret = []  # 結果

my_dir = './光譜資料集/'
file_list = listdir(my_dir)
for cur_file in file_list:
    print("正在處理:", cur_file)
    df = None
    try:
        df = pd.read_table(my_dir + cur_file, skiprows=26)
        # df['nb'] = df['Raw Counts (Ref.)'] - df['Raw Counts (Target)']
        df['nb'] = round(df['Reflect. %'] / 100, 2)
        df = df.set_index('Wvl')['nb']
    except Exception as e:
        print("出錯啦, 大兄弟!", e)

    # 計算着一大坨資料名額
    cur_lst = []
    # 被檔案名作為 第一個資料
    cur_lst.append(cur_file)
    # RSI
    rsi = df.loc[R990] / df.loc[R720]
    cur_lst.append(rsi)

    # NDSI
    ndsi = (df.loc[R860] - df.loc[R720]) / (df.loc[R860] + df.loc[R720])
    cur_lst.append(ndsi)

    # FD_NDVI
    fdndvi = (df.loc[R730] - df.loc[R525]) / (df.loc[R730] + df.loc[R525])
    cur_lst.append(fdndvi)
    # RENDVI
    cur_lst.append((df.loc[R750] - df.loc[R705]) / (df.loc[R750] + df.loc[R705]))
    # mNd705
    cur_lst.append((df.loc[R750] - df.loc[R705]) / (df.loc[R750] + 2 * df.loc[R445]))
    # GNDVI
    cur_lst.append((df.loc[R790] - df.loc[R550]) / (df.loc[R790] + df.loc[R550]))
    # SAVI
    cur_lst.append(1.5 * (df.loc[R870] - df.loc[R680]) / (df.loc[R870] + df.loc[R680] + 0.16))
    # OSIVI
    cur_lst.append(1.16 * (df.loc[R810] - df.loc[R680]) / (df.loc[R810] - df.loc[R680] + 0.16))
    # MSAVI
    cur_lst.append(
        2 * (df.loc[R800] + 1 - ((2 * df.loc[R800] + 1) * 2 - 8 * (df.loc[R800] - df.loc[R670])) * 0.5)
    )
    # DCNA
    cur_lst.append(
        (df.loc[R720] - df.loc[R700]) / (df.loc[R700] - df.loc[R670]) / (df.loc[R700] - df.loc[R670] + 0.03)
    )
    # CIgreen
    cur_lst.append(((df.loc[R840] - df.loc[R870]) / df.loc[R550]) - 1)
    # NINI
    try:
        cur_lst.append(
            (log10(1 / df.loc[R1510]) - log10(1 / df.loc[R1680])) / (log10(1 / df.loc[R1510]) + log10(1 / df.loc[R1680]))
        )
    except:
        print(cur_file, "log 計算有問題")
        cur_lst.append('lg計算失敗')
    # TVI
    cur_lst.append(
        0.5 * (120 * (df.loc[R750] - df.loc[R550]) - 200 * (df.loc[R670] - df.loc[R550]))
    )
    # DSI
    cur_lst.append(df.loc[R800] - df.loc[R680])

    # 将目前結果添加到 ret 中
    ret.append(cur_lst)

# 最後将 [[],[]...] 再存為 DataFrame
col = ['資料檔案名', 'RSI', 'NDSI', 'FD_NDVI', 'RENDVI', 'mNd705', 'GNDVI', 'SAVI',
       'OSIVI', 'MSAVI', 'DCNA', 'CIgreen', 'NINI', 'TVI','DSI']

data = pd.DataFrame(ret,
                    columns=col)
print()
print("*"*50)
print("正在存儲到,  表格...")

data.to_excel("D:/光譜資料.xlsx", index=False)

end = time.time()
print(f"處理完畢! 共處理 {len(file_list)} 個檔案,  總共用時 {round(end - start, 2)} 秒")
print("*"*50)      

其實蠻簡單的一個腳本, 循環讀取檔案夾的資料, 然後來弄即可. 發現現在這換了 台式電腦, 果然很穩, 同時 讀取 文本資料, 遠比 Excel 檔案, 效率高了 近 10倍.

正在處理: 20190930_00128.sed
正在處理: 20190930_00129.sed
正在處理: 20190930_00130.sed
正在處理: 20190930_00131.sed
正在處理: 20190930_00132.sed
正在處理: 20190930_00133.sed
正在處理: 20190930_00134.sed
正在處理: 20190930_00135.sed
正在處理: 20190930_00136.sed
正在處理: 20190930_00137.sed
正在處理: 20190930_00138.sed
正在處理: 20190930_00139.sed
正在處理: 20190930_00140.sed
正在處理: 20190930_00141.sed
正在處理: 20190930_00142.sed
正在處理: 20190930_00143.sed
正在處理: 20190930_00144.sed
正在處理: 20190930_00145.sed
正在處理: 20190930_00146.sed
正在處理: 20190930_00147.sed
......

**************************************************
正在存儲到,  表格...
處理完畢! 共處理 1447 個檔案,  總共用時 5.58 秒
**************************************************
[Finished in 6.1s]      
  • 經常談什麼批量處理檔案, 其實就是, 結構化的, 對單個檔案, 邏輯寫好, 然後循環處理 n 多個檔案.
  • 對名額計算, 設計好号資料結構, 清單, 字典這些, 最好是用 生成器 yield 來弄, 最後再 list 出來, 提高性能
  • 3年多了, 真實覺得 Pandas 是真的好用哇, 尤其是處理方面, 主要是現在很多邏輯, 是通過 sql 這樣産生對比.