最近想用python批量處理數(shù)據(jù),把自己網(wǎng)上找答案的過程整理了一下,希望對(duì)大家有用。
問題:
一個(gè)文件夾中有38個(gè)txt文件,這38個(gè)txt的命名各不相同,要把這38個(gè)txt文件中的數(shù)據(jù)整合到一個(gè)txt中。
思路:
獲取所有txt文件的名稱、路徑,然后用for循環(huán)遍歷每個(gè)txt文件,進(jìn)行處理。最后將處理后的數(shù)據(jù)合并。
先看下總體代碼,后面有具體解釋。
import pandas as pd
import numpy as np
import os
os.getcwd()
os.chdir('/Users/Heihei/Desktop/EX2data/data')
path = '/Users/Heihei/Desktop/EX2data/data'
os.listdir(path)
datalist = []
for i in os.listdir(path):
if os.path.splitext(i)[1] == '.txt':
datalist.append(i)
df = pd.DataFrame()
for txt in datalist:
data_path = os.path.join(path,txt)
df_txt = pd.read_table(data_path,index_col = False)
df_txt['sub_n'] = txt[:2]
df_txt_sx = df_txt[df_txt['split'].isin([1,2])]
df = pd.concat([df,df_txt_sx],axis=0, ignore_index=True)
df.head(5)
df.tail(5)
df.shape
df.isnull().sum()
df.duplicated().sum()
df.to_csv('/Users/Heihei/Desktop/EX2data/data/Total_data',index=False)
代碼解釋
1. 獲取路徑
#載入需要的模塊
import pandas as pd
import numpy as np
import os
os.getcwd() #獲取當(dāng)前工作路徑,查看是否是自己的目標(biāo)路徑
os.chdir('/Users/Heihei/Desktop/EX2data/data') #如果不是,改到目標(biāo)路徑
path = '/Users/Heihei/Desktop/EX2data/data'
os.listdir(path) #查看目標(biāo)路徑下有哪些數(shù)據(jù)
結(jié)果顯示(中間有很多了txt我把它省略了):
['.DS_Store',
'01lwj.txt',
......
'38lym.txt']
由上面可以看到,出現(xiàn)了一個(gè)“ .DS_Store”文件。如果我們直接用os.listdir(path)進(jìn)行循環(huán),會(huì)報(bào)錯(cuò)。
“ .DS_Store” 文件是Mac OS系統(tǒng)的Finder 用來存儲(chǔ)這個(gè)文件夾的顯示屬性的:比如文件圖標(biāo)的擺放位置。具體可以看這篇文章:http://mini.eastday.com/mobile/180317092251931.html#。 因此。我們需要重新建立一個(gè)不包含該文件的list,新的list只含有txt數(shù)據(jù)。
datalist = []
for i in os.listdir(path):
if os.path.splitext(i)[1] == '.txt': #選取后綴為txt的文件加入datalist
datalist.append(i)
datalist #查看datalist
os.path.splitext
把文件分為文件名和擴(kuò)展名。比如os.path.splitext(a.txt)的結(jié)果為a 以及 .txt 。因此,os.path.splitext(i)[1]的意思就是取出文件的后綴名。
除了該函數(shù)外,還有一個(gè)os.path.split 的函數(shù),該函數(shù)用來把路徑分為文件名與文件目錄,比如“/user/heihei/data.txt” ,經(jīng)過作用后可以被分為“/user/heihei”和 “data.txt”
另外,注意python中的順序。list[x:y] 是從第“x+1”個(gè)數(shù)(因?yàn)閜ython的第一個(gè)數(shù)是0)開始,直到y(tǒng)結(jié)束(不包含y)。如list = [0,1,2] , list[1:2]的結(jié)果是[1]。
2. 循環(huán)合并數(shù)據(jù)
df = pd.DataFrame()
for txt in datalist:
data_path = os.path.join(path,txt) #列出path路徑下目標(biāo)文件的絕對(duì)路徑,將其賦值給data_path
df_txt = pd.read_table(data_path,index_col = False) #讀取目標(biāo)txt文件,不把原Data第一列作為索引
df_txt['sub_n'] = txt[:2] #取出前面的數(shù)值,并賦值給sub_n這一列(合并后我需要知道哪些數(shù)據(jù)來自哪個(gè)文件)
df_txt_sx = df_txt[df_txt['split'].isin([1,2])] #用isin方法進(jìn)行數(shù)據(jù)篩選(我的數(shù)據(jù)中split一列有3個(gè)值,我只需要改列值為1,2的行,其他行不需要)
df = pd.concat([df,df_txt_sx],axis=0, ignore_index=True) #(將篩選后的數(shù)據(jù)加到df框中。axis=0表示上下合并,axis=1表示左右合并,ignore_index=True表示忽略原來索引。除了concat函數(shù)外,也可以用df.append實(shí)現(xiàn),但是還要改索引,比concat方法會(huì)麻煩點(diǎn))
3. 檢查合并完的數(shù)據(jù)
df.head(5) #檢查最開始5行數(shù)據(jù)
df.tail(5) #檢查最后5行數(shù)據(jù)
df.shape #查看數(shù)據(jù)框行列是否和預(yù)期一樣
df.isnull().sum() #查看是否有缺失值
df.duplicated().sum() 查看是否有重復(fù)值
4. 保存數(shù)據(jù)
df.to_csv('/Users/Heihei/Desktop/EX2data/data/Total_data',index=False)
# index=False 表示不保存索引數(shù)據(jù)
#之后如果要讀取的話,直接df.read_csv('Total_data', index_col=False)就能得到 df框。
公眾號(hào): 爾冬禾(PsyHeheihei),文章更新速度比這里稍微快一點(diǎn),主要跟數(shù)據(jù)分析相關(guān)內(nèi)容和一些個(gè)人思考。歡迎交流
參考資料:
1.Python讀取/批量讀取文件
2.python中split()、os.path.split()函數(shù)用法
3.【python】如何批量讀取文件夾的所有文件數(shù)據(jù),os模塊與open函數(shù)結(jié)合使用實(shí)例
4.python中pandas.DataFrame排除特定行方法示例