pandas學習筆記 - 文件的寫入和輸出


# -*- coding: utf-8 -*-
"""
Created on Tue Aug 28 22:19:26 2018
 
@author: Dev
"""
import numpy as np import pandas as pd import sys import csv import xlrd, xlwt import json

 

 
讀取csv格式文件
ex1.csv的文件內容:
 
 
path = 'D:\Learning\Program\Python Data Analyze'    # 設置文件路徑
df = pd.read_csv(path + '\\data\\ex1.csv')  # 自動識別csv文件的分隔符
df1 = pd.read_table(path + '\\data\\ex1.csv', sep=',')    # 需手動指定分隔符


#執行結果(df和df1相同): a b c d message 0 1   2   3   4 hello 1  5   6   7   8 world 2  9  10  11  12     foo

 

ex2.csv內容:

 

df2 = pd.read_csv(path + '\\data\\ex2.csv', header=None)    # 指定文件中沒有column,會自動根據列的數量指定


#執行結果: 0 1   2   3      4 0 1   2   3   4 hello 1  5   6   7   8 world 2  9  10  11  12    foo

 

# 設置列名,並將message列設置為索引列
names = ['a', 'b', 'c', 'd', 'message'] df3 = pd.read_csv(path + '\\data\\ex2.csv', names=names, index_col='message') print(df3.index) print(df3) #執行結果: Index(['hello', 'world', 'foo'], dtype='object', name='message') a b c d message hello 1   2   3   4 world 5   6   7   8 foo 9  10  11  12

 

csv_mindex.csv內容:
 
# 將兩列設置為索引
parsed = pd.read_csv(path + '\\data\\csv_mindex.csv', index_col=['key1', 'key2']) 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

 

# ex3.txt中有多種空格類型(空格 TAB等)

 

# 將txt文件轉為列表格式(轉換后格式較亂,不易使用)
list_a = list(open(path + '\\data\\ex3.txt')) print(list_a) --執行結果: [' A B C\n', 'aaa -0.264438 -1.026059 -0.619500\n', 'bbb 0.927272 0.302904 -0.032399\n', 'ccc -0.264273 -0.386314 -0.217601\n', 'ddd -0.871858 -0.348382 1.100491\n'] # 在分隔符中使用正則表達式對數據進行分割(\s 表示多種不可見字符, +表示存在多個)
result = pd.read_table(path + '\\data\\ex3.txt', sep='\s+') print(result) # 執行結果: A B C aaa -0.264438    -1.026059        -0.619500 bbb 0.927272     0.302904        -0.032399 ccc -0.264273    -0.386314        -0.217601 ddd -0.871858    -0.348382         1.100491

 

ex4.csv內容:

# 跳過指定行
df4 = pd.read_csv(path + '\\data\\ex4.csv', skiprows=[0, 2, 3]) print(df4) #執行結果: a b c d message 0 1   2   3   4 hello 1  5   6   7   8 world 2  9  10  11  12     foo

 

 ex5.csv內容:
 
df5 = pd.read_csv(path + '\\data\\ex5.csv') print(df5) print(pd.isnull(df5))   # 判斷是否有為空的值

#執行結果:
 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 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 # 將指定的值設置為空值
df5 = pd.read_csv(path + '\\data\\ex5.csv', na_values=['NULL']) print(df5) #執行結果:
 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 # 設置多個na_values值
sentinels = {'message': ['foo', 'NA'], 'something': ['two']} df5 = pd.read_csv(path + '\\data\\ex5.csv', na_values=sentinels) print(df5) #執行結果:
 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

 

ex6.csv內容:

一共9999行數據,后面省略。。。

# 逐行讀取
result = pd.read_csv(path + '\\data\\ex6.csv') print(result)   # 行數過多時,一次讀取所有行會顯得多余


# 執行結果:
 one two three four key 0 0.467976 -0.038649 -0.295344 -1.824726 L 1    -0.358893  1.404453  0.704965 -0.200638 B 2    -0.501840  0.659254 -0.421691 -0.057688 G 3     0.204886  1.074134  1.388361 -0.982404 R 4     0.354628 -0.133116  0.283763 -0.837063 Q 5     1.817480  0.742273  0.419395 -2.251035 Q 6    -0.776764  0.935518 -0.332872 -1.875641 U ... ... ... ... .. 9995  2.311896 -0.417070 -1.409599 -0.515821 L 9996 -0.479893 -0.650419  0.745152 -0.646038 E 9997  0.523331  0.787112  0.486066  1.093156 K 9998 -0.362559  0.598894 -1.843201  0.887292 G 9999 -0.096376 -1.012999 -0.657431 -0.573315 0 df = pd.read_csv(path + '\\data\\ex6.csv', nrows=5) # 只讀取前5行


# 執行結果:
 one two three four key 0 0.467976 -0.038649 -0.295344 -1.824726 L 1 -0.358893  1.404453  0.704965 -0.200638 B 2 -0.501840  0.659254 -0.421691 -0.057688 G 3  0.204886  1.074134  1.388361 -0.982404 R 4  0.354628 -0.133116  0.283763 -0.837063 Q # 將1000行數據存儲到chunker中
chunker = pd.read_csv(path + '\\data\\ex6.csv', chunksize=1000) print(chunker) # 執行結果:
<pandas.io.parsers.TextFileReader object at 0x000000000BCC4F98>


# 再統計key值的取值次數
total = pd.Series([]) for piece in chunker: total = total.add(piece['key'].value_counts(), fill_value=0)    # fill_value 使用0填充空值
print(total[:10]) # 執行結果:
0    151.0
1    146.0
2    152.0
3    162.0
4    171.0
5    157.0
6    166.0
7    164.0
8    162.0
9    150.0 dtype: float64

 

注:df.column.values 和 df.column.value_counts()的區別:
values以列表形式返回指定column的所有取值
value_counts()返回指定column的不同取值次數
value_counts(1)返回指定column的不同取值頻率
 
 
文件寫出
data = pd.read_csv(path + '\\data\\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

 

data.to_csv(path + '\\data\\ex5_2.csv') # 寫出文件到指定目錄(windows下,后面要輸出的文件名開頭必須有個表示路徑的'\\',不然不會生成文件,也不報錯,很詭異。。。)

輸出的ex5_2.csv的內容:

 

data.to_csv(sys.stdout, sep='|')    # 以豎線分隔

# 執行結果:

 |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

 

data.to_csv(sys.stdout, na_rep='NULL')  # 以NULL填充na值

# 執行結果
,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

 

data.to_csv(sys.stdout, index=False, header=False)  #   不選取索引名和列名

# 執行結果:
one,1,2,3.0,4,
two,5,6,,8,world
three,9,10,11.0,12,foo

 

data.to_csv(sys.stdout, index=False, columns=['a', 'b', 'c'])   # 重新設置列名

# 執行結果:
a,b,c
1,2,3.0
5,6,
9,10,11.0

 

# 將Series寫入csv文件:

# pd.date_range() 用於生成一個固定頻率的時間索引
dates = pd.date_range('1/1/2000', periods=7, freq='H')  # start 起始值, end 結束值, freq頻率, periods周期
ts = pd.Series(np.arange(7), index=dates)   # 使用生成的時間索引指定
ts.to_csv(path + '\\data\\tseries.csv')
print(ts.index)


# 執行結果:
DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 01:00:00',
               '2000-01-01 02:00:00', '2000-01-01 03:00:00',
               '2000-01-01 04:00:00', '2000-01-01 05:00:00',
               '2000-01-01 06:00:00'],
              dtype='datetime64[ns]', freq='H')

生成的tseries.csv的內容:

 

# parse_dates 指定某些列是否被解析為日期,布爾值或列表
data2 = pd.read_csv(path + '\\data\\tseries.csv', header=None, parse_dates=True)
print(data2)


# 執行結果:
                     0  1
0  2000-01-01 00:00:00  0
1  2000-01-01 01:00:00  1
2  2000-01-01 02:00:00  2
3  2000-01-01 03:00:00  3
4  2000-01-01 04:00:00  4
5  2000-01-01 05:00:00  5
6  2000-01-01 06:00:00  6

 

Tips: 如果IDE包含IPython(我用的是Spyder),在IPython界面輸入  cd $path命令即可進入path變量所指定的目錄下,就不用每次讀取和寫出時都帶path了。

 

ex7.csv內容:

 

f = open('ex7.csv')    # 打開csv文件
reader = csv.reader(f)    # 使用csv.reader()讀取
for line in reader:    # 逐行打印
    print(line)

# 執行結果:
['a', 'b', 'c']
['1', '2', '3']
['1', '2', '3', '4']

# 轉換成列表
lines = list(csv.reader(open('ex7.csv')))
header, values = lines[0], lines[1:]    # 取第一行作為header,其余行作為values
# 先將values解壓為元組,再與header合並,組成字典
data_dict = {h: v for h,v in zip(header, zip(*values))}
print(data_dict)

# 執行結果:
{'a': ('1', '1'), 'b': ('2', '2'), 'c': ('3', '3')}

 

使用csv.Dialect自定義文件格式

# 通常用於數據中包含特殊字符的情況
 
class my_dialect(csv.Dialect):
  # 自定義一個繼承csv.Dialect的類
    lineterminator = '\n'   # 每行結束符
    delimiter = ';'         # 定義分隔符
    quotechar = '"'         # 定義給包含特殊字符的數據所添加的符號
    quoting = csv.QUOTE_MINIMAL # 僅對包含特殊字符的數據加quotechar中定義的符號
 
csv.register_dialect('mycsv', my_dialect)   # 使用自定義名稱mycsv 注冊上面的類
with open('mydata.csv', 'w') as file_obj:  # 使用自定義文件格式寫入數據
    writer = csv.writer(file_obj, 'mycsv')
    writer.writerow(('one', 'two', 'three'))
    writer.writerow(('1', '2', '3'))
    writer.writerow(('4', '5', '6'))
    writer.writerow(('7', '8', '9'))
生成的mydata.csv內容:

 

 

在mydata.csv文件中加入特殊符號(5前面加了單引號):

 

# 不帶dialect的讀取:
with open('mydata.csv', 'r') as file_obj:
    reader = csv.reader(file_obj)
    for row in reader:
        print(row)


# 執行結果:
['one;two;three']
['1;2;3']
["4;'5;6"]
['7;8;9']

 

# 帶dialect的讀取:
with open('mydata.csv', 'r') as file_obj:
    reader = csv.reader(file_obj, dialect='mycsv')
    for row in reader:
        print(row)


# 執行結果:
['one', 'two', 'three']
['1', '2', '3']
['4', "'5", '6']
['7', '8', '9']

發現在使用了自定義的dialect后,只有帶特殊符號的數據被加了雙引號("'5")

 
 
將數據轉儲為Excel的xls工作薄(xlwt)
wb = xlwt.Workbook()
print(wb)   # Workbook類型的對象

# 執行結果:
<xlwt.Workbook.Workbook object at 0x000000000BD1DC88>

 

wb.add_sheet('first_sheet', cell_overwrite_ok=True) # 新增名為first_sheet的sheet頁,並且可覆蓋寫入
wb.get_active_sheet()   # 獲取當前sheet頁序號
ws_1 = wb.get_sheet(0)  # 根據獲取的序號激活該sheet頁
print(ws_1)
wb.add_sheet('first_sheet', cell_overwrite_ok=True) # 新增名為first_sheet的sheet頁,並且可覆蓋寫入
wb.get_active_sheet()   # 獲取當前sheet頁序號
ws_1 = wb.get_sheet(0)  # 根據獲取的序號激活該sheet頁
print(ws_1)

# 執行結果:
<xlwt.Worksheet.Worksheet object at 0x000000000BD1D748>

 

ws_2 = wb.add_sheet('second_sheet') # 在wb中再增加一張sheet頁ws_2
data = np.arange(1, 65).reshape(8, 8) 
ws_1.write(0, 0, 100)   # 在0行0列的位置寫入100

# 將生成的data分別寫入wb的兩個sheet頁中
for row in range(data.shape[0]):
    for col in range(data.shape[1]):
        # 需要將數據類型為numpy.int32的數組元素轉換為int類型
        ws_1.write(row, col, int(data[row, col]))   # 先寫行,后寫列
        ws_2.write(row, col, int(data[col, row]))   # 先寫列, 后寫行
 
wb.save('workbook.xls') # 保存結果到xls文件中

first_sheet:

second_sheet:

 

生成xlsx工作簿(xlrd)
book = xlrd.open_workbook('workbook.xls')   # 讀取剛才生成的工作簿文件
print(book) # Book對象

# 執行結果:
<xlrd.book.Book object at 0x000000000BC5B9E8>

 

常用方法:
print(book.nsheets)    # 查看sheet總頁數
print(book.sheet_names())  # 查看所有的sheet頁名

# 執行結果:
2
['first_sheet', 'second_sheet']

 

sheet_1 = book.sheet_by_name('first_sheet')  # 通過頁名獲取sheet頁
sheet_2 = book.sheet_by_index(1)    # 通過索引獲取sheet頁
print(sheet_1.name) # sheet頁名稱
print(sheet_1.nrows)    # 總行數
print(sheet_1.ncols)    # 總行數

# 執行結果:
first_sheet
8
8

 

c1 = sheet_1.cell(0, 0)   # 返回(0, 0)(返回類型為xlrd.sheet.Cell)
print(c1)
print(c1.value) # 只返回實際值
print(c1.ctype) # 返回c1對應的數據類型(0: None, 1: string, 2: number, 3: date, 4: bool, 5: error)

# 執行結果:
number:1.0
1.0
2

 

print(sheet_2.row(1))   # 獲取第1行的數據
result = [number.value for number in sheet_2.row(1)]# 通過.value獲取實際值
print(result)

# 執行結果:
[number:2.0, number:10.0, number:18.0, number:26.0, number:34.0, number:42.0, number:50.0, number:58.0]
[2.0, 10.0, 18.0, 26.0, 34.0, 42.0, 50.0, 58.0]

 

print(sheet_2.row_values(1))    # 直接返回包含實際值的列表,省去了上面的轉換過程
print(sheet_2.row_types(0)) # 返回第0行的數據類型列表(對應關系同ctype)

# 執行結果:
[2.0, 10.0, 18.0, 26.0, 34.0, 42.0, 50.0, 58.0]
array('B', [2, 2, 2, 2, 2, 2, 2, 2])

 

print(sheet_2.col(3))   # 獲取第4列的數據
print(sheet_2.col_values(3, start_rowx=3, end_rowx=7))  # 獲取第四列中第4行到第7行的數據
print(sheet_2.row_values(3, start_colx=3, end_colx=7)) # 獲取第四行中第4列到第7列的數據

# 執行結果:
[number:25.0, number:26.0, number:27.0, number:28.0, number:29.0, number:30.0, number:31.0, number:32.0]
[28.0, 29.0, 30.0, 31.0]
[28.0, 36.0, 44.0, 52.0]

 

# 逐行打印
for row in range(sheet_1.ncols):
    for col in range(sheet_1.nrows):
        print(sheet_1.cell(row, col).value)

# 執行結果:
1.0
2.0
3.0
4.0
5.0
... ...
60.0
61.0
62.0
63.0
64.0

 

其他常用的數據格式

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)

asjson = json.dumps(result) # 字典 -> 字符串
print(asjson)

siblings = pd.DataFrame(result['siblings'], columns=['name', 'age', 'pet']) # 字典 -> DataFrame
print(siblings)

# 執行結果:
{'name': 'Wes', 'places_lived': ['United States', 'Spain', 'Germany'], 'pet': None, 'siblings': [{'name': 'Scott', 'age': 25, 'pet': 'Zuko'}, {'name': 'Katie', 'age': 33, 'pet': 'Cisco'}]}

{"name": "Wes", "places_lived": ["United States", "Spain", "Germany"], "pet": null, "siblings": [{"name": "Scott", "age": 25, "pet": "Zuko"}, {"name": "Katie", "age": 33, "pet": "Cisco"}]}

    name  age    pet
0  Scott   25   Zuko
1  Katie   33  Cisco

 

二進制數據格式
df = pd.read_csv('ex1.csv')
df.to_pickle('frame_pickle.bin')    # DataFrame -> 二進制格式
pickle = pd.read_pickle('frame_pickle.bin') # 二進制 -> DataFrame
print(pickle)

# 執行結果:
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

查看轉換的frame_pickle.bin二進制文件內容:

 

HDF5格式(可壓縮格式)
使用高性能HD5格式進行數據存儲和訪問,格式類似字典,適合存儲格式統一的分層(hierarchical)數據
相關鏈接:
store = pd.HDFStore('mydata.h5')    # 生成存儲文件
store['obj1'] = df          # 將數據保存在指定data_column下
store['obj1_col'] = df['a']
print(store)
print(store['obj1'])    # 使用data_column訪問數據
store.close()   # 關閉文件,然后會將store中的數據實際寫入本地文件

# 執行結果:
<class 'pandas.io.pytables.HDFStore'>
File path: mydata.h5
/obj1                frame        (shape->[3,5])
/obj1_col            series       (shape->[3])  

   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

關閉后在本地查看mydata.h5文件:

 

HDF5的壓縮模式
data = pd.DataFrame(np.random.standard_normal((10000000, 10)))    # 使用標准正態分布生成一個較大數據量的DF進行對比
normal_store = pd.HDFStore('normal_store.h5')  # 普通方式
normal_store['data'] = data
normal_store.close()
# complevel指定壓縮強度(0->9 數值越大,強度越高,0是不壓縮)
# complib指定要使用的壓縮庫。可用的lib:
    # zlib: 默認lib
    # lzo: 壓縮和解壓都快
    # bzip2: 壓縮率高
    # blosc: 壓縮和解壓都快
# pandas 0.20.2中又細分除了幾種壓縮lib,這里就不做詳細介紹了
compress_store = pd.HDFStore('compress_store.h5', complevel=9, complib='bzip2') # 這里選擇壓縮率和強度較高的方式進行壓縮
compress_store['data'] =  data
compress_store.close()

對比文件大小:

壓縮了約144MB, 好像也不是特別明顯,是不是數據量還不夠大。。。 ):

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM