您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關python如何使用pandas數據加載、存儲與文件格式的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
數據加載、存儲與文件格式
pandas提供了一些用于將表格型數據讀取為DataFrame對象的函數。其中read_csv和read_talbe用得最多
pandas中的解析函數:
函數 說明
read_csv 從文件、URL、文件型對象中加載帶分隔符的數據,默認分隔符為逗號
read_table 從文件、URL、文件型對象中加載帶分隔符的數據。默認分隔符為制表符("\t")
read_fwf 讀取定寬列格式數據(也就是說,沒有分隔符)
read_clipboard 讀取剪貼板中的數據,可以看做read_table的剪貼板版。在將網頁轉換為表格時很有用
下面介紹一下這些函數在將文本數據轉換為DataFrame時所用到的一些技術。這些函數的選項可以劃分為以下幾個大類:
(1)索引:將一個或多個列當做返回的DataFrame處理,以及是否從文件、用戶獲取列名
(2)類型推斷和數據轉換:包括用戶定義值的轉換、缺失值標記列表等。(類型推斷是這些函數中最重要的功能之一)
(3)日期解析:包括組合功能,比如將分散在多個列中的日期時間信息組合成結果中的單個列。
(4)迭代:支持對大文件進行逐塊迭代。
(5)不規整數據問題:跳過一些行、頁腳、注釋或其他一些不重要的東西(比如成千上萬個逗號隔開的數值數據)
1. 讀寫文本格式的數據:
(1)由于該文件以逗號分隔,所以我們可以使用read_csv將其讀入一個DataFrame:
import pandas as pd import numpy as np
#'ex1.csv'的內容如下: # a,b,c,d,message # 1,2,3,4,hello # 5,6,7,8,world # 9,10,11,12,foo df=pd.read_csv('ex1.csv') print df #輸出結果如下: # a b c d message # 0 1 2 3 4 hello # 1 5 6 7 8 world # 2 9 10 11 12 foo
(2)我們也可以用read_table,只不過需要指定分隔符而己:
df=pd.read_table('ex1.csv',sep=',') print df #輸出結果如下: # a b c d message # 0 1 2 3 4 hello # 1 5 6 7 8 world # 2 9 10 11 12 foo
(3)讀入文件可以讓pandas為其分配默認的列名,也可以自己定義列名:
print pd.read_csv('ex1.csv',header=None) #輸出結果如下: # 0 1 2 3 4 # 0 a b c d message # 1 1 2 3 4 hello # 2 5 6 7 8 world # 3 9 10 11 12 foo print pd.read_csv('ex1.csv',names=['a','b','c','d','message']) #輸出結果如下: # a b c d message # 0 a b c d message # 1 1 2 3 4 hello # 2 5 6 7 8 world # 3 9 10 11 12 foo
(4)假如希望將message列做成DataFrame的索引,也可以明確表示要將該列放到索引4的位置上,也可以通過index_col參數指定"message"
names=['a','b','c','d','message'] print pd.read_csv('ex1.csv',names=names) #輸出結果如下: # a b c d message # 0 a b c d message # 1 1 2 3 4 hello # 2 5 6 7 8 world # 3 9 10 11 12 foo print pd.read_csv('ex1.csv',names=names,index_col='message') #輸出結果如下: # a b c d # message # message a b c d # hello 1 2 3 4 # world 5 6 7 8 # foo 9 10 11 12
(5)如果希望將多個列做成一個層次化索引,只需傳入由列編號或列名組成的列表即可:
#'csv_mindex.csv'的內容如下: # key1,key2,value1,value2 # one,a,1,2 # one,b,3,4 # one,c,5,6 # one,d,7,8 # two,a,9,10 # two,b,11,12 # two,c,13,14 # two,d,15,16 parsed=pd.read_csv('csv_mindex.csv',index_col=['key1','key2']) #index_col表示為行索引 print parsed # value1 value2 # key1 key2 # one a 1 2 # b 3 4 # c 5 6 # d 7 8 # two a 9 10 # b 11 12 # c 13 14 # d 15 16
(6)有些表示可能不是用固定的分隔符去分隔字段的(比如空白符或其它字符串)。對于這些情況,可以編寫一個正則表達式來作為read_table
# 的分隔符。看下面的文本文件 #'ex3.txt'的內容如下 # A B C, # aaa -0.264438 -1.026059 -0.619500 # bbb 0.9283898 0.3928928 -0.032388 # ccc -0.264327 -0.386313 -0.217601 # ddd -0.878218 -0.348238 1.1004919 print list(open('ex3.txt')) #輸出結果如下: # [' A B C,\n', # 'aaa -0.264438 -1.026059 -0.619500\n', # 'bbb 0.9283898 0.3928928 -0.032388\n', # 'ccc -0.264327 -0.386313 -0.217601\n', # 'ddd -0.878218 -0.348238 1.1004919'] #該文件各個字段由數量不定的空白符分隔,則可以用正則表達式\s+表示: #正則表達式:\s表示空白符,\S非空白符,+表示后面會一直匹配下去。即\s+會匹配多個空格符 result=pd.read_table('ex3.txt',sep='\s+') print result #輸出結果如下: # A B C, # aaa -0.264438 -1.026059 -0.619500 # bbb 0.928390 0.392893 -0.032388 # ccc -0.264327 -0.386313 -0.217601 # ddd -0.878218 -0.348238 1.100492 #注意:這里由于列名比數據行的數量少(即A,B,C三個列名,但是列的數據是4列),所以read_table推斷第一列應該是DataFrame的索引。
(7)skiprows跳過文件的一些行,可以幫助處理各種各樣的異形文件格式
#'ex4.csv'的內容如下: ##hey! # a,b,c,d,message # #just wanted to make thins more difficult for u # # who reads CSV files with computers,anyway? # 1,2,3,4,hello # 5,6,7,8,world # 9,10,11,12,foo print pd.read_csv('ex4.txt',skiprows=[0,2,3]) #輸出結果如下: # a b c d message # 0 1 2 3 4 hello # 1 5 6 7 8 world # 2 9 10 11 12 foo
(8)缺失值處理是文件解析任務中的一個重要組成部分。缺失數據經常是要么沒有(空字符串),要么用某個標記值表示。
#默認情況下,pandas會用一組經常出現的標記值進行識別,如NA,-1.#IND以及NULL等。 #'ex5.csv'的內容如下: # something,a,b,c,d,message # one,1,2,3,4,NA # two,5,6,,8,world # three,9,10,11,12,foo result=pd.read_csv('ex5.csv') print result #輸出結果如下: # something a b c d message # 0 one 1 2 3.0 4 NaN # 1 two 5 6 NaN 8 world # 2 three 9 10 11.0 12 foo print pd.isnull(result) #查看為缺失值 #輸出結果如下: # something a b c d message # 0 False False False False False True # 1 False False False True False False # 2 False False False False False False
(9) na_values可以接受一組用于表示缺失值的字符串:
result=pd.read_csv('ex5.csv',na_values=['NULL']) print result #輸出結果如下: # something a b c d message # 0 one 1 2 3.0 4 NaN # 1 two 5 6 NaN 8 world # 2 three 9 10 11.0 12 foo
(10) 可以用一個字典為各列指定不同的NA標記值
sentinels={'message':['foo','NA'],'something':['two']} #將message列中的foo標成NA,something的two也標成NA print pd.read_csv('ex5.csv',na_values=sentinels) #輸出結果如下: # something a b c d message # 0 one 1 2 3.0 4 NaN # 1 NaN 5 6 NaN 8 world # 2 three 9 10 11.0 12 NaN read_csv/read_table函數的參數:
參數 說明 path 表示文件系統位置、url、文件型對象的字符串 sep或delimiter 用于對行各字段進行拆分的字符序列或正則表達式 header 用作列名的行號。默認為0(第一行),如果沒有header行就應該設置為None index_col 用作行索引的列編號或列名。可以是單個名稱/數字或多個名稱/數字組成的列表(層次化索引) names 用于結果的列名列表,結合header=None skiprows 需要忽略的行數(從文件開始處算起),或需要跳過的行號列表(從0開始) na_values 一組用于替換NA的值 comment 用于將注釋信息從行尾拆分出去的字符(一個或多個) parse_dates 嘗試將數據解析為日期,默認為False.如果為True,則嘗試解析所有列。此外,還可以指定需要解析的一組 列號或列名。如果列表的元素為列表或元組,就會將多個列組合到一起再進行日期解析工作(例如,日期/時間 分別位于兩個列中) keep_date_col 如果連接多列解析日期,則保持參與連接的列。默認為False. converters 由列號/列名跟函數之間的映射關系組成的字典。例如,{‘foo':f}會對foo列的所有值應用函數f dayfirst 當解析有歧義的日期時,將其看做國際格式(例如:7/6/2012->June,7,2012).默認為False date_parser 用于解析日期的函數 nrows 需要讀取的行數(從文件開始處算起) iterator 返回一個TextParser以便逐塊讀取文件 chunksize 文件塊的大小(用于迭代) skip_footer 需要忽略的行數(從文件末尾處算起) verbose 打印各種解析器輸出信息,比如“非數值列中缺失值的數量”等 encoding 用于unicode的文本編碼格式。 squeeze 如果數據經解析后僅含一列,則返回Series thousands 千分位分隔符,如“,”或“。”
逐塊讀取文本文件:
在處理很大文件時,或找出大文件中的參數集以便于后續處理時,你可能只想讀取文件的一小部分或逐塊對文件進行迭代。
import pandas as pd import numpy as np from pandas import Series,DataFrame #'ex6.csv'的內容如下: # <class 'pandas.core.frame.DataFrame'> # Int64Index:10000 entries, 0 to 9999 # Data columns: # one 10000 non-null values # two 10000 non-null values # three 10000 non-null values # four 10000 non-null values # key 10000 non-null values # dtypes: float64(4),object(1) print pd.read_csv('ex6.csv',nrows=5) #nrows=5取前6行,下標從0開始 #要逐塊讀取文件,需要設置chunksize(行數) chunker=pd.read_csv('ex6.csv',chunksize=1000) print chunker #輸出結果如下: # <pandas.io.parsers.TextFileReader object at 0x102ebb5d0> #read_csv所返回的這個TextParser對象使你可以根據chunksize對文件進行逐塊迭代。比如說: #我們可以迭代處理ex6.csv,將值計數聚合到"key"列中。 tot=Series([]) for piece in chunker: tot=tot.add(piece['key'].value_counts(),fill_value=0) #value_counts計算個數,fill_value為空時填充0 tot=tot.order(ascending=False) #此版本Series沒有有order,可以換成sort_value # tot=tot.sort_value(ascending=False) print tot #報key錯誤
將數據寫到文本格式:
數據也可以被輸出為分隔符格式文本
data=pd.read_csv('ex5.csv') #輸出結果如下: print data #輸出結果如下: # something a b c d message # 0 one 1 2 3.0 4 NaN # 1 two 5 6 NaN 8 world # 2 three 9 10 11.0 12 foo
DataFrame的to_csv方法:
(1)數據寫入:to_csv,利用DataFrame的to_csv方法,我們可以將數據寫到一個以逗號分隔的文件中
print data.to_csv('out.csv') #out.csv的內容如下: # ,something,a,b,c,d,message # 0,one,1,2,3.0,4, # 1,two,5,6,,8,world # 2,three,9,10,11.0,12,foo
(2)當然也可以使用其他分隔符(由于這里直接寫到sys.stdout控制臺,所以僅僅是打印出文本結果而己)
print data.to_csv(sys.stdout,sep='|') #輸出結果如下: # None # |something|a|b|c|d|message # 0|one|1|2|3.0|4| # 1|two|5|6||8|world # 2|three|9|10|11.0|12|foo # None
(3)缺失值在輸出結果中會被表示為空字符串,若希望將其表示為別的標記值用na_sep='NULL'
print data.to_csv(sys.stdout,na_rep='NULL') #輸出結果如下: # ,something,a,b,c,d,message # 0,one,1,2,3.0,4,NULL # 1,two,5,6,NULL,8,world # 2,three,9,10,11.0,12,foo # None
(4)如果沒有設置其它選項,則會寫出行和列的標簽。當然,它們也都可以被禁用:index=False,header=False
print data.to_csv(sys.stdout,index=False,header=False) #行標簽index,列標簽header #輸出結果如下: # one,1,2,3.0,4, # two,5,6,,8,world # three,9,10,11.0,12,foo # None
(5)還可以只寫出一部分的列,并以你指定的順序排序:index=False,columns=[]
print data.to_csv(sys.stdout,index=False,columns=['a','b','c']) #輸出結果如下: # a,b,c # 1,2,3.0 # 5,6, # 9,10,11.0 # None
Series的to_csv方法:
(1)Series的to_csv方法,將Series寫入到.csv文件中
dates=pd.date_range('1/1/2000',periods=7) #date_range可以生成時間序列,periods=7表示可以生成7個時間序列,從2000/1/1開始 print dates #輸出結果如下: # DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04', # '2000-01-05', '2000-01-06', '2000-01-07'], # dtype='datetime64[ns]', freq='D') ts=Series(np.arange(7),index=dates) #index行索引用dates ts.to_csv('tseries.csv') #tseries.csv的內容如下: # 2000-01-01,0 # 2000-01-02,1 # 2000-01-03,2 # 2000-01-04,3 # 2000-01-05,4 # 2000-01-06,5 # 2000-01-07,6
(2)read_csv也可以將csv文件讀取為Series(Series.read_csv,而DataFrame則用pd.read_csv),但還有一個更為方更的from_csv方法
print Series.from_csv('tseries.csv',parse_dates=True) #輸出結果如下: # 2000-01-01 0 # 2000-01-02 1 # 2000-01-03 2 # 2000-01-04 3 # 2000-01-05 4 # 2000-01-06 5 # 2000-01-07 6 # dtype: int64
from_csv和read_csv中參數整理如下:
pandas.read_csv參數整理 讀取CSV(逗號分割)文件到DataFrame 也支持文件的部分導入和選擇迭代 更多幫助參見:http://pandas.pydata.org/pandas-docs/stable/io.html 參數: filepath_or_buffer : str,pathlib。str, pathlib.Path, py._path.local.LocalPath or any object with a read() method (such as a file handle or StringIO) 可以是URL,可用URL類型包括:http, ftp, s3和文件。對于多文件正在準備中 本地文件讀取實例:://localhost/path/to/table.csv sep : str, default ‘,' 指定分隔符。如果不指定參數,則會嘗試使用逗號分隔。分隔符長于一個字符并且不是‘\s+',將使用python的語法分析器。并且忽略數據中的逗號。正則表達式例子:'\r\t' delimiter : str, default None 定界符,備選分隔符(如果指定該參數,則sep參數失效) delim_whitespace : boolean, default False. 指定空格(例如' ‘或者' ‘)是否作為分隔符使用,等效于設定sep='\s+'。如果這個參數設定為Ture那么delimiter 參數失效。 在新版本0.18.1支持 header : int or list of ints, default ‘infer' 指定行數用來作為列名,數據開始行數。如果文件中沒有列名,則默認為0,否則設置為None。如果明確設定header=0 就會替換掉原來存在列名。header參數可以是一個list例如:[0,1,3],這個list表示將文件中的這些行作為列標題(意味著每一列有多個標題),介于中間的行將被忽略掉(例如本例中的2;本例中的數據1,2,4行將被作為多級標題出現,第3行數據將被丟棄,dataframe的數據從第5行開始。)。 注意:如果skip_blank_lines=True 那么header參數忽略注釋行和空行,所以header=0表示第一行數據而不是文件的第一行。 names : array-like, default None 用于結果的列名列表,如果數據文件中沒有列標題行,就需要執行header=None。默認列表中不能出現重復,除非設定參數mangle_dupe_cols=True。 index_col : int or sequence or False, default None 用作行索引的列編號或者列名,如果給定一個序列則有多個行索引。 如果文件不規則,行尾有分隔符,則可以設定index_col=False 來是的pandas不適用第一列作為行索引。 usecols : array-like, default None 返回一個數據子集,該列表中的值必須可以對應到文件中的位置(數字可以對應到指定的列)或者是字符傳為文件中的列名。例如:usecols有效參數可能是 [0,1,2]或者是 [‘foo', ‘bar', ‘baz']。使用這個參數可以加快加載速度并降低內存消耗。 as_recarray : boolean, default False 不贊成使用:該參數會在未來版本移除。請使用pd.read_csv(...).to_records()替代。 返回一個Numpy的recarray來替代DataFrame。如果該參數設定為True。將會優先squeeze參數使用。并且行索引將不再可用,索引列也將被忽略。 squeeze : boolean, default False 如果文件值包含一列,則返回一個Series prefix : str, default None 在沒有列標題時,給列添加前綴。例如:添加‘X' 成為 X0, X1, ... mangle_dupe_cols : boolean, default True 重復的列,將‘X'...'X'表示為‘X.0'...'X.N'。如果設定為false則會將所有重名列覆蓋。 dtype : Type name or dict of column -> type, default None 每列數據的數據類型。例如 {‘a': np.float64, ‘b': np.int32} engine : {‘c', ‘python'}, optional Parser engine to use. The C engine is faster while the python engine is currently more feature-complete. 使用的分析引擎。可以選擇C或者是python。C引擎快但是Python引擎功能更加完備。 converters : dict, default None 列轉換函數的字典。key可以是列名或者列的序號。 true_values : list, default None Values to consider as True false_values : list, default None Values to consider as False skipinitialspace : boolean, default False 忽略分隔符后的空白(默認為False,即不忽略). skiprows : list-like or integer, default None 需要忽略的行數(從文件開始處算起),或需要跳過的行號列表(從0開始)。 skipfooter : int, default 0 從文件尾部開始忽略。 (c引擎不支持) skip_footer : int, default 0 不推薦使用:建議使用skipfooter ,功能一樣。 nrows : int, default None 需要讀取的行數(從文件頭開始算起)。 na_values : scalar, str, list-like, or dict, default None 一組用于替換NA/NaN的值。如果傳參,需要制定特定列的空值。默認為‘1.#IND', ‘1.#QNAN', ‘N/A', ‘NA', ‘NULL', ‘NaN', ‘nan'`. keep_default_na : bool, default True 如果指定na_values參數,并且keep_default_na=False,那么默認的NaN將被覆蓋,否則添加。 na_filter : boolean, default True 是否檢查丟失值(空字符串或者是空值)。對于大文件來說數據集中沒有空值,設定na_filter=False可以提升讀取速度。 verbose : boolean, default False 是否打印各種解析器的輸出信息,例如:“非數值列中缺失值的數量”等。 skip_blank_lines : boolean, default True 如果為True,則跳過空行;否則記為NaN。 parse_dates : boolean or list of ints or names or list of lists or dict, default False boolean. True -> 解析索引 list of ints or names. e.g. If [1, 2, 3] -> 解析1,2,3列的值作為獨立的日期列; list of lists. e.g. If [[1, 3]] -> 合并1,3列作為一個日期列使用 dict, e.g. {‘foo' : [1, 3]} -> 將1,3列合并,并給合并后的列起名為"foo" infer_datetime_format : boolean, default False 如果設定為True并且parse_dates 可用,那么pandas將嘗試轉換為日期類型,如果可以轉換,轉換方法并解析。在某些情況下會快5~10倍。 keep_date_col : boolean, default False 如果連接多列解析日期,則保持參與連接的列。默認為False。 date_parser : function, default None 用于解析日期的函數,默認使用dateutil.parser.parser來做轉換。Pandas嘗試使用三種不同的方式解析,如果遇到問題則使用下一種方式。 1.使用一個或者多個arrays(由parse_dates指定)作為參數; 2.連接指定多列字符串作為一個列作為參數; 3.每行調用一次date_parser函數來解析一個或者多個字符串(由parse_dates指定)作為參數。 dayfirst : boolean, default False DD/MM格式的日期類型 iterator : boolean, default False 返回一個TextFileReader 對象,以便逐塊處理文件。 chunksize : int, default None 文件塊的大小, See IO Tools docs for more informationon iterator and chunksize. compression : {‘infer', ‘gzip', ‘bz2', ‘zip', ‘xz', None}, default ‘infer' 直接使用磁盤上的壓縮文件。如果使用infer參數,則使用 gzip, bz2, zip或者解壓文件名中以‘.gz', ‘.bz2', ‘.zip', or ‘xz'這些為后綴的文件,否則不解壓。如果使用zip,那么ZIP包中國必須只包含一個文件。設置為None則不解壓。 新版本0.18.1版本支持zip和xz解壓 thousands : str, default None 千分位分割符,如“,”或者“." decimal : str, default ‘.' 字符中的小數點 (例如:歐洲數據使用',‘). float_precision : string, default None Specifies which converter the C engine should use for floating-point values. The options are None for the ordinary converter, high for the high-precision converter, and round_trip for the round-trip converter. 指定 lineterminator : str (length 1), default None 行分割符,只在C解析器下使用。 quotechar : str (length 1), optional 引號,用作標識開始和解釋的字符,引號內的分割符將被忽略。 quoting : int or csv.QUOTE_* instance, default 0 控制csv中的引號常量。可選 QUOTE_MINIMAL (0), QUOTE_ALL (1), QUOTE_NONNUMERIC (2) or QUOTE_NONE (3) doublequote : boolean, default True 雙引號,當單引號已經被定義,并且quoting 參數不是QUOTE_NONE的時候,使用雙引號表示引號內的元素作為一個元素使用。 escapechar : str (length 1), default None 當quoting 為QUOTE_NONE時,指定一個字符使的不受分隔符限值。 comment : str, default None 標識著多余的行不被解析。如果該字符出現在行首,這一行將被全部忽略。這個參數只能是一個字符,空行(就像skip_blank_lines=True)注釋行被header和skiprows忽略一樣。例如如果指定comment='#' 解析‘#empty\na,b,c\n1,2,3' 以header=0 那么返回結果將是以'a,b,c'作為header。 encoding : str, default None 指定字符集類型,通常指定為'utf-8'. List of Python standard encodings dialect : str or csv.Dialect instance, default None 如果沒有指定特定的語言,如果sep大于一個字符則忽略。具體查看csv.Dialect 文檔 tupleize_cols : boolean, default False Leave a list of tuples on columns as is (default is to convert to a Multi Index on the columns) error_bad_lines : boolean, default True 如果一行包含太多的列,那么默認不會返回DataFrame ,如果設置成false,那么會將改行剔除(只能在C解析器下使用)。 warn_bad_lines : boolean, default True 如果error_bad_lines =False,并且warn_bad_lines =True 那么所有的“bad lines”將會被輸出(只能在C解析器下使用)。 low_memory : boolean, default True 分塊加載到內存,再低內存消耗中解析。但是可能出現類型混淆。確保類型不被混淆需要設置為False。或者使用dtype 參數指定類型。注意使用chunksize 或者iterator 參數分塊讀入會將整個文件讀入到一個Dataframe,而忽略類型(只能在C解析器中有效) buffer_lines : int, default None 不推薦使用,這個參數將會在未來版本移除,因為他的值在解析器中不推薦使用 compact_ints : boolean, default False 不推薦使用,這個參數將會在未來版本移除 如果設置compact_ints=True ,那么任何有整數類型構成的列將被按照最小的整數類型存儲,是否有符號將取決于use_unsigned 參數 use_unsigned : boolean, default False 不推薦使用:這個參數將會在未來版本移除 如果整數列被壓縮(i.e. compact_ints=True),指定被壓縮的列是有符號還是無符號的。 memory_map : boolean, default False 如果使用的文件在內存內,那么直接map文件使用。使用這種方式可以避免文件再次進行IO操作。
手工處理分隔符格式:csv python內置函數使用
大部分存儲在磁盤上的表格型數據都能用pandas.read_table進行加載。然而有進還是需要手工處理。
由于接收到含有畸形行的文件而使read_table出毛病的情況并不少見。
對于任何單字符分隔符文件,可以直接使用python內置的csv模塊。將任意己打開的文件或文件型的對象傳給csv.reader
import csv f=open('ex7.csv') reader=csv.reader(f) print reader #輸出結果是一個對象:<_csv.reader object at 0x10d7c7600> for line in reader: print line #對這個reader進行迭代將會為每行產生一個元組 #輸出結果如下: # ['a', 'b', 'c'] # ['1', '2', '3'] # ['1', '2', '3', '4']
為了使數據格式合乎要求,你需要對其做些調整
lines=list(csv.reader(open('ex7.csv'))) print lines #輸出結果如下: # [['a', 'b', 'c'], ['1', '2', '3'], ['1', '2', '3', '4']] print lines[0],lines[1] header,values=lines[0],lines[1:] print zip(*values) #zip(iterable),將對象中對應的元素打包成一個個元組。a=[1,2,3] b=[2,4,5] zip(a,b)=[(1,2),(2,4),(3,5)] #輸出結果如下: # [('1', '1'), ('2', '2'), ('3', '3')] data_dict={h:v for h, v in zip(header,zip(*values))} print data_dict #輸出結果如下:結果得到的是列表,不是元組 # {'a': ('1', '1'), 'c': ('3', '3'), 'b': ('2', '2')}
CSV文件的形式有很多。只需定義csv.Dialect的一個子類即可定義出新格式(如專門的分隔符、字符串引用約定、行結束符等)
class my_dialect(csv.Dialect): lineterminator = '\n' delimiter = ';' quotechar = '"' quoting = 0 reader=csv.reader(f,dialect=my_dialect) print reader #輸出結果如下: # <_csv.reader object at 0x10628a6e0> with open('mydata.csv','w')as f: writer=csv.writer(f,dialect=my_dialect) writer.writerow(('one','two','three')) writer.writerow(('1','2','3')) writer.writerow(('1', '2', '3')) #打開mydata.csv內容如下: # one;two;three # 1;2;3 # 1;2;3
各個csv語句的參數也可以用關鍵字的形式提供給csv.reader,無需定義子類:
reader=csv.reader(f,delimiter='|')
csv.writer用于手工輸出分隔符文件,它接受一個己打開且可寫的文件對象以及跟csv.reader相同的那些語句和選項:
#csv.writer先創建一個write對象,然后用writerow寫入,可以一行行寫入,也可以字典寫入 headers = ['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume'] rows = [{'Symbol':'AA', 'Price':39.48, 'Date':'6/11/2007', 'Time':'9:36am', 'Change':-0.18, 'Volume':181800}, {'Symbol':'AIG', 'Price': 71.38, 'Date':'6/11/2007', 'Time':'9:36am', 'Change':-0.15, 'Volume': 195500}, {'Symbol':'AXP', 'Price': 62.58, 'Date':'6/11/2007', 'Time':'9:36am', 'Change':-0.46, 'Volume': 935000}, ] with open('stock.csv','w') as f: writer=csv.DictWriter(f,headers) writer.writeheader() writer.writerows(rows) #stock.csv的結果如下: # Symbol,Price,Date,Time,Change,Volume # AA,39.48,6/11/2007,9:36am,-0.18,181800 # AIG,71.38,6/11/2007,9:36am,-0.15,195500 # AXP,62.58,6/11/2007,9:36am,-0.46,935000
csv產生的數據都是字符串類型的,它不會做任何其它類型的轉換,如果你需要做這樣的類型轉換,必須自己手動去實現:
#下面是一個在csv數據上執行其他類型轉換的例子: col_types=[str,float,str,str,float,int] with open('stock.csv') as f: f_csv=csv.reader(f) headers=next(f_csv) print headers #輸出結果如下 # ['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume'] for row in f_csv: rows=tuple(convert(value) for convert,value in zip(col_types,row)) print rows #輸出結果如下: # ('AA', 39.48, '6/11/2007', '9:36am', -0.18, 181800) # ('AIG', 71.38, '6/11/2007', '9:36am', -0.15, 195500) # ('AXP', 62.58, '6/11/2007', '9:36am', -0.46, 935000) #下面是一個轉換字典中特定字段的例子: field_types = [ ('Price', float), ('Change', float), ('Volume', int) ] with open('stock.csv') as f: for row in csv.DictReader(f): #row指的是每一行 print row row.update((key,coversion(row[key])) for key,coversion in field_types) #key:price conversion:float,row.update(key)如果key在row中找到,則conversion(row[key])的值, # row[key]是指這個key的value值 print row #輸出如下:第一行是第一個print row輸出,下面一個才是轉換后的print row的輸出 # {'Symbol': 'AA', 'Volume': '181800', 'Time': '9:36am', 'Date': '6/11/2007', 'Price': '39.48', 'Change': '-0.18'} # {'Symbol': 'AA', 'Volume': 181800, 'Time': '9:36am', 'Date': '6/11/2007', 'Price': 39.48, 'Change': -0.18}
csv 參數選項如下:
參數 說明 delimiter 用于分隔字段的單字符字符串。默認為“,” lineterminator 用于寫操作的行結束符,默認為“\r\n” quotechar 用于帶有特殊字符(如分隔符)的字段的引用符號。默認為“"” quoting 引用約定。可選值包括csv.quote_all(引用所有字段), csv.quote_minimal(只引用帶有諸如分隔符之類特殊字符的字段)默認為quote_minimal skipinitialspace 忽略分隔符后面的空白符。默認False doublequote 如何處理字段內的引用符號。如果為True,則雙寫。 escapechar 用于對分隔符進行轉義的字符串。默認禁用
總結:
(1)對于那些使用復雜分隔符或多字符分隔符的文件,csv模塊就無能為力了。在這種情況下,就只能用字符串split方法或正則表達式方法re.split進行拆分和其它整理工作了。
(2)最后,如果你讀取CSV數據的目的是做數據分析和統計的話,你可能需要看一看 Pandas 包。Pandas 包含了一個非常方便的函數叫 pandas.read_csv() ,它可以加載CSV數據到一個 DataFrame 對象中去。 然后利用這個對象你就可以生成各種形式的統計、過濾數據以及執行其他高級操作了
json格式的讀取與寫入:
通過json.loads可將json字符串轉換成python形式,即從磁盤中讀取
import pandas as pd import numpy as np from pandas import Series,DataFrame import sys import json
obj=""" {"name":"Wes", "places_lived":["United States","Spain","Germany"], "pet":null, "siblings":[{"name":"Scott","age":25,"pet":"Zuko"}, {"name":"Katie","age":33,"pet":"Cisco"}] } """ result=json.loads(obj) print result #輸出結果如下: {u'pet': None, u'siblings': [{u'pet': u'Zuko', u'age': 25, u'name': u'Scott'}, {u'pet': u'Cisco', u'age': 33, u'name': u'Katie'}], u'name': u'Wes', u'places_lived': [u'United States', u'Spain', u'Germany']}
相反json.dumps則將python對象轉換成JSON格式。即寫入
asjson=json.dumps(result) print asjson #輸出結果與上面的result一樣的json格式
將(一個或一組)json對象轉換為DataFrame或其它便于分析的數據結構就由你決定了。
最簡單方便的方式是:向DataFrame構造器傳入一組Json對象,并選取數據字段的子集(即可以選一部分字段,也可以全部選定)
siblings=DataFrame(result['siblings'],columns=['name','age']) #選取result中的'siblings',列選取name,age兩列 print siblings #輸出的結果如下: # name age # 0 Scott 25 # 1 Katie 33
XML和HTML:Web信息收集
python有許多可以讀寫HTML和xml格式數據的庫。lxml就是其中之一,它可以高效地解析大件。
lxml有多個編程接口。首先我們要用lxml.html處理HTML,然后再用lxml.objectify做一些XML處理。
HTML文件處理:
許多網站都將數據放到HTML表格中以便在瀏覽器中查看,但不能以一種更易于機器閱讀的格式(如Json、HTML或XML)進行下載
(1)首先,找到你希望獲取數據的URL,利用urllib2將其打開,然后用lxml解析得到的數據流。
import pandas as pd import numpy as np from pandas import Series,DataFrame import sys import json from urllib2 import urlopen from lxml.html import parse from lxml import objectify
parsed=parse(urlopen('http://finance.yahoo.com/q/op?s=AAPL+Options')) doc=parsed.getroot() #通過這個對象可以獲取特定類型的所有HTML標簽(tag) #獲取HTML中的鏈接是a標簽的,可使用findall方法 links=doc.findall('.//a') #得到所有a標簽的對象,以列表形式顯示 print links[15:20] #輸出結果如下:輸出的是Html元素對象 # [<Element a at 0x1085206d8>, # <Element a at 0x108520730>, # <Element a at 0x108520788>, # <Element a at 0x1085207e0>, # <Element a at 0x108520838>]
(2)要得到URL和鏈接文本,必須使用各對象的get方法(針對URL)和text_content方法(針對顯示文本)
lnk=links[15] print lnk #顯示的是下標為28的a標簽的元素對象 print lnk.get('href') #用get方法得到以"href"的URL #輸出結果如下:/quote/AAPL180601P00145000?p=AAPL180601P00145000 print lnk.text_content() #輸出結果如下:AAPL180601P00145000 #使用下面這條列表推導式可獲取文檔中的全部URL urls=[lnk.get('href') for lnk in doc.findall('.//a')] print urls #輸出結果如下: # ['https://finance.yahoo.com/', '#Navigation', '#market-summary', '#Main', '#Aside', # 'https://mail.yahoo.com/?.intl=us&.lang=en-US&.partner=none&.src=finance', '/quote/AAPL?p=AAPL', # '/quote/AAPL/key-statistics?p=AAPL', '/quote/AAPL/profile?p=AAPL', '/quote/AAPL/financials?p=AAPL',]
(3)表格:從文檔中找出正確表格,有些網站會給目標表格加上一個id屬性。下面是兩個分別放置看漲數據和跌數據的表格。
每個表格都有標題行。tr是表格中的行,th表頭單元格,td數據單元格
tables=doc.findall('.//table') print tables #輸出結果如下:是表格對象 # [<Element table at 0x10f1a09f0>, <Element table at 0x10f1a0a48>] calls=tables[0] print calls #輸出的是對象 #每個表格都有標題行。tr是表格中的行,th表頭單元格,td數據單元格 #先取出標題行 rows=calls.findall('.//tr') print rows #輸出結果:也是行的元素對象如<Element tr at 0x108bffaa0>
#寫一個函數:可以根據傳入的參數得到相關表格中的數據 def _unpack(row,kind='td'): elts=row.findall('.//%s' % kind) return [val.text_content() for val in elts] print _unpack(rows[1]) #取數據單元格中的數據值 #輸出結果如下:取rows[1]即第2行的數據 # ['AAPL180608C00130000', '2018-05-04 11:45PM EDT', '130.00', '36.90', '53.40', '54.70', '0.00', '-', '1', '1', '0.00%'] print _unpack(rows[1],kind='th') #取表頭單元格的值,即列的標題 #輸出結果:['Strike','Symbol','Last','Chg','Bid','Ask']
(4)把所有步驟結合起來,將數據轉換為一個DataFrame。由于數值型數據仍然是字符串格式,所以我們希望將部分弄轉換為浮點數格式。
雖然可以手工實現該功能,但是pandas就有一個TextParser類可以自動類型轉換(read_csv和其它解析函數其實在內部都用到了它)
from pandas.io.parsers import TextParser def parse_option_data(table): rows=table.findall('.//tr') header=_unpack(rows[0],kind='th') data=[_unpack(r) for r in rows[1:]] return TextParser(data,names=header).get_chunk() aa=parse_option_data(table=tables) print DataFrame(aa)
利用lxml.objectify解析xml: 可具體看另一篇專門介紹xml解析文件
aa.xml的內容如下:
<?xml version="1.0" ?> <zAppointments reminder="15"> <appointment> <begin>1181251680</begin> <uid>040000008200E000</uid> <alarmTime>1181572063</alarmTime> <state></state> <location></location> <duration>1800</duration> <subject>Bring pizza home</subject> </appointment> <appointment> <begin>1234360800</begin> <duration>1800</duration> <subject>Check MS Office website for updates</subject> <location></location> <uid>604f4792-eb89-478b-a14f-dd34d3cc6c21-1234360800</uid> <state>dismissed</state> </appointment> </zAppointments>
def parseXML(xmlFile): """ Parse the xml :param xmlFile: :return: """ f=open(xmlFile) #1.先打開文件 xml=f.read() #2.讀取文件內容 f.close() tree=etree.parse(StringIO(xml)) #3.用etree.parse解析xml文件的樹結構 context=etree.iterparse(StringIO(xml)) #4.etree.iterparse迭代解析xml文件的內容 for action,elem in context: if not elem.text: text="None" else: text=elem.text print elem.tag+"=>"+text if __name__=="__main__": parseXML("aa.xml")
def parseXML(xmlFile): """ Parse the xml :param xmlFile: :return: """ f=open(xmlFile) xml=f.read() f.close() tree=etree.parse(StringIO(xml)) context=etree.iterparse(StringIO(xml)) for action,elem in context: if not elem.text: text="None" else: text=elem.text print elem.tag+"=>"+text if __name__=="__main__": parseXML("aa.xml") #輸出結果如下: # begin = > 1181251680 # uid = > 040000008200E000 # alarmTime = > 1181572063 # state = > None # location = > None # duration = > 1800 # subject = > Bring # pizza # home # appointment = > # # begin = > 1234360800 # duration = > 1800 # subject = > Check # MS # Office # website # for updates # location = > None # uid = > 604 # f4792 - eb89 - 478 # b - a14f - dd34d3cc6c21 - 1234360800 # state = > dismissed # appointment = > # # zAppointments = >
2.二進制數據格式:寫入與讀取
(1)使用python內置的pickle序列化讀取和存儲數據
實現數據的二進制格式存儲最簡單的辦法之一是使用python內置的pickle序列化。
為了使用方便,pandas對象都有一個用于將數據以pickle形式保存到磁盤上的to_pickle方法。
相反,從磁盤上讀取read_pickle。
import pandas as pd import numpy as np from pandas import Series,DataFrame #二進制數據格式保存 frame=pd.read_csv('ex1.csv') print frame #輸出結果如下: # a b c d message # 0 1 2 3 4 hello # 1 5 6 7 8 world # 2 9 10 11 12 foo (1)可用to_pickle保存到磁盤 frame.to_pickle('frame_pickle') (2)還有一個也很好用的pickle函數pandas.load將數據讀回到python,load也沒有了,現在是read_pickle讀取數據 # pd.load('frame_pickle') #load已經不能用了,現在是read_pickle print pd.read_pickle('frame_pickle')
警告:pickle僅建議用于短期存儲格式。其原因是很難保證格式永遠是穩定的。
今天的pickle的對象無法被后續版本的庫unpickle出來。
(2)使用HDF5格式實現高效讀寫磁盤上以二進制格式存儲的科學數據。
HDF5支持多種壓縮器的即時壓縮,能更高效地存儲重復模式數據,對于那些非常大的無法直接放入內存的數據集,
HDF5就是不錯的選擇,因為它可以高效地分塊讀寫。
python中的HDF5庫有兩個接口(即PyTables和h6py),h6py提供了一種直接而高級的HDF5 API訪問接口,
而PyTables則抽象了HDF5的許多細節以提供多種靈活的數據容器、表索引、查詢功能以及對核外計算技術的某些支持。
import pandas as pd import numpy as np from pandas import Series,DataFrame import matplotlib.pyplot as plt import tables #二進制數據格式保存 frame=pd.read_csv('ex1.csv') print frame #輸出結果如下: # a b c d message # 0 1 2 3 4 hello # 1 5 6 7 8 world # 2 9 10 11 12 foo #兩個函數用于生成數據 random_state = np.random.RandomState(1999) def make_random_cluster_points(n_samples, random_state=random_state): mu_options = np.array([(-1, -1), (1, 1), (1, -1), (-1, 1)]) sigma = 0.2 mu_choices = random_state.randint(0, len(mu_options), size=n_samples) means = mu_options[mu_choices] return means + np.random.randn(n_samples, 2) * sigma, mu_choices def plot_clusters(data, clusters, name): plt.figure() colors = ["#9b59b6", "#3498db", "#e74c3c", "#2ecc71"] for i in np.unique(clusters): plt.scatter(data[clusters==i, 0], data[clusters==i, 1], color=colors[i]) plt.axis('off') plt.title('Plot from %s' % name) #(1)數據寫入到磁盤:open_file(文件名,'w'),create_array() data, clusters = make_random_cluster_points(10000) plot_clusters(data, clusters, "data in memory") # plt.show() #畫圖展示 #PyTables存儲數據到磁盤 sample_data,sample_clusters=make_random_cluster_points(10000) #調用函數生成數據 hdf5_path="my_data.hdf5" #寫入的文件名 hdf5_file=tables.open_file(hdf5_path,mode='w') data_storage=hdf5_file.create_array(hdf5_file.root,'data',sample_data) #hdf5_file.root即"/",data為創建array文件名相當于"/data",data里存儲的是sample_data的數據.data像文件名 clusters_storage=hdf5_file.create_array(hdf5_file.root,'clusters',sample_clusters) hdf5_file.close() #(2)數據的讀取:open_file(文件名,'r'),hdf5_file.root.data[:] hdf5_path="my_data.hdf5" read_hdf5_file=tables.open_file(hdf5_path,mode='r') hdf5_data=read_hdf5_file.root.data[:] #讀取read_hdf5_file根目錄下的數據名稱為data的全部數據 hdf5_clusters=read_hdf5_file.root.clusters[:] #讀取read_hdf5_file根目錄下的數據名稱為clusters的全部數據 read_hdf5_file.close() plot_clusters(hdf5_data,hdf5_clusters,"PyTables Array") plt.show()
注意:HDF5不是數據庫。它最適合用作”一次寫多次讀“的數據集。雖然數據可以在任何時候被添加到文件中,
但如果同時發生多個寫操作,文件就可能會被破壞。
(3)讀取Microsoft Excel文件
pandas的ExcelFile類文件讀取存儲在Excel中表格型數據。由于ExcelFile用到了(python讀取excel表格的包)xlrd和openpyxl包,所以先得安裝它們才行。
# 讀取excel文件: xls_file=pd.ExcelFile('data.xls') #存放在某個工作表中的數據可以通過parse讀取到DataFrame中 table=xls_file.parse('Sheet1')
3.使用HTML和Web API:request包中的get來讀取數據
import pandas as pd import numpy as np from pandas import Series,DataFrame import matplotlib.pyplot as plt import tables import requests import json # url='https://twitter.com/search?q=python+pandas' url='https://twitter.com/search?q=python%20pandas&src=typd' resp=requests.get(url) print resp.text data=json.loads(resp.text) #將resp轉化成json格式 print data print data.keys() #用一個列表定義出感興趣的tweet字段,然后將results列表傳給DataFrame: tweet_fields=['created_at','from_user','id','text'] tweets=DataFrame(data['result'],columns=tweet_fields) print tweets.ix[7]
4.使用數據庫
sqlite3數據庫:讀取數據庫數據
import pandas as pd import numpy as np from pandas import Series,DataFrame import matplotlib.pyplot as plt import tables import requests import json import sqlite3 (1)數據連接 query=""" CREATE TABLE test (a VARCHAR (20),b VARCHAR (20), c REAL, d INTEGER ); """ con=sqlite3.connect(':memory:') con.execute(query) con.commit() (2)插入數據 data=[('Atlanta','Georgia',1.25,6), ('Tallahassee','Florida',2.6,3), ('Sacramento','California',1.7,5)] stmt='INSERT INTO test VALUES(?,?,?,?)' con.executemany(stmt,data) con.commit() #查詢數據,即讀取數據庫數據 cursor=con.execute('select * from test') rows=cursor.fetchall() print rows #輸出結果如下:sqlite3取出的是列表 [(u'Atlanta', u'Georgia', 1.25, 6), (u'Tallahassee', u'Florida', 2.6, 3), (u'Sacramento', u'California', 1.7, 5)] (3)可以將這個元組列表傳給DataFrame的構造器,但還需要列名(位于游標的description屬性中) print cursor.description #輸出結果如下: (('a', None, None, None, None, None, None), ('b', None, None, None, None, None, None), ('c', None, None, None, None, None, None), ('d', None, None, None, None, None, None)) (4)轉換為DataFrame result=DataFrame(rows,columns=zip(*cursor.description)[0]) print result #輸出結果如下: # a b c d # 0 Atlanta Georgia 1.25 6 # 1 Tallahassee Florida 2.60 3 # 2 Sacramento California 1.70 5 (5)上面的方法每查一次就得寫一次,pandas有一個可以簡化該過程的read_sql函數(位于pandas.io.sql模塊)。 # 只需傳入select語句和連接對象即可。 import pandas.io.sql as sql # print sql.read_sql('select * from test',con) #或者直接用pd.read_sql不用先引入sql也一樣的 df= pd.read_sql('select * from test',con) #輸出結果如下: # a b c d # 0 Atlanta Georgia 1.25 6 # 1 Tallahassee Florida 2.60 3 # 2 Sacramento California 1.70 5 aa=DataFrame(df) print aa
mysql數據庫:讀取數據庫數據
#讀取mysql中的數據 import pymysql import configparser config =configparser (1)連接數據庫 db=pymysql.connect("localhost","root", "root","imooc") cursor=db.cursor() #使用游標創建一個游標對象 (2)使用execute()方法執行sql查詢 cursor.execute("select * from test1") data=cursor.fetchall() print data #輸出結果如下:4條數據,mysql取出的形式是元組 # ((1, 'tang seng', 79, 'xi tian qu jing', '11783213,131313133,78271783918'), # (2, 'zhu ba jie', 61, 'xi tian qu jing', '787138912,83918933'), # (3, 'sun wu kong', 91, 'ji tian da sheng', '1378219389,17898932183,1841898344,1989839898'), # (4, 'sha seng', 71, 'xi tian qu jing', '1649281938,15089328109')) # (3)列名信息在cursor.description中,及列的其它信息也在 print cursor.description # #查看結果如下: # ((u'id', 3, None, 11, 11, 0, 0), # (u'user_name', 253, None, 20, 20, 0, 1), # (u'score', 3, None, 2, 2, 0, 1), # (u'over', 253, None, 40, 40, 0, 1), # (u'mobile', 253, None, 100, 100, 0, 1)) print type(zip(*cursor.description)[0]) (4)將data放入DataFrame中,pandas必須是list才可以轉化為DataFrame,而此處的Data是元組,故先轉化為list才可以用 result=DataFrame(list(data),columns=zip(*cursor.description)[0]) print result #輸出結果如下: # id user_name score over \ # 0 1 tang seng 79 xi tian qu jing # 1 2 zhu ba jie 61 xi tian qu jing # 2 3 sun wu kong 91 ji tian da sheng # 3 4 sha seng 71 xi tian qu jing # # mobile # 0 11783213,131313133,78271783918 # 1 787138912,83918933 # 2 1378219389,17898932183,1841898344,1989839898 # 3 1649281938,15089328109 (5)可以用read_sql一次性獲取: import pandas.io.sql as sql result=sql.read_sql('select * from test1',db) print result #輸出結果如下: # id user_name score over \ # 0 1 tang seng 79 xi tian qu jing # 1 2 zhu ba jie 61 xi tian qu jing # 2 3 sun wu kong 91 ji tian da sheng # 3 4 sha seng 71 xi tian qu jing # # mobile # 0 11783213,131313133,78271783918 # 1 787138912,83918933 # 2 1378219389,17898932183,1841898344,1989839898 # 3 1649281938,15089328109 db.close()
注意:(1)DataFrame接受轉換的是list形式:sqlit3用fetchall取出的是列表,所以可以直接放在DataFrame中,而mysql取出來的是元組,故要先轉化成list.
mongoDB數據庫:讀取數據庫數據
NoSQL數據庫有許多不同的形式。有些是簡單的字典式鍵值對存儲,另一些則是基于文檔的(其中的基本單元是字典型的對象)。
from pandas import Series,DataFrame import pymongo import datetime # import configparser # config =configparser (1)mongodb數據庫的連接 con=pymongo.MongoClient('localhost',port=27017) (2)創建數據庫 # tweets=con.test_database (3)創建集合:一組文件存儲在mongodb中,相當于數據庫的各個表 # collection=tweets.test_collection post = {"author": "Mike", "text": "My first blog post!", "tags": ["mongodb", "python", "pymongo"], "date": datetime.datetime.utcnow()} (4)插入文件 posts=tweets.posts post_id=posts.insert_one(post).inserted_id (5)查詢相關的數據 import pprint pprint.pprint(posts.find_one({"author":"Mike"})) (6)字典放入DataFrame中 p=DataFrame(post,columns=post.keys()) print p
感謝各位的閱讀!關于“python如何使用pandas數據加載、存儲與文件格式”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。