文章目錄
- 直接存儲
- join list 變成字符串存儲
- json.dumps序列化存儲以及json.loads反序列化讀取
- 總結
之所以分析這個問題,是因為讀者在跟第三方數據供應商對接數據的時候,老是會遇到數據加載都會出錯的問題,其中一個原因就是list類型數據沒有正確儲存,于是筆者在這篇文章里面詳細分析一下list數據怎么優雅的寫入csv以及讀取.
直接存儲
第一種方法,直接存,不做任何轉換
def direct_write_read():path = Path(__file__).parent.joinpath('direct.csv')df = pd.DataFrame({'id': [1,2,3],'tags': [['tag1', 'tag2'], ['tag3'], ['tag4', 'tag5']]})df.to_csv(path, index=False, encoding='utf-8')rd_df = pd.read_csv(path, encoding='utf-8')print(rd_df['tags'])
csv文件內容
id,tags
1,"['tag1', 'tag2']"
2,['tag3']
3,"['tag4', 'tag5']"
程序打印結果
0 ['tag1', 'tag2']
1 ['tag3']
2 ['tag4', 'tag5']
Name: tags, dtype: object
整個程序能運行,應為都是用的python寫文件讀取文件,但是csv文件內容不標準,這種處理方式存在潛在問題,容易出現python語言能讀寫,但是換成其它語言程序讀取此csv就可能出現錯誤,因此不推薦這種處理方式.
join list 變成字符串存儲
第二種方法,使用','.join(list)
方法將列表連接成字符串存csv,讀取的時候再將字符串按照連接字符進行分割.
def join_write_read():path = Path(__file__).parent.joinpath('join.csv')df = pd.DataFrame({'id': [1,2,3],'tags': [['tag1', 'tag2'], ['tag3'], ['tag4', 'tag5']]})df['append'] = df['tags'].apply(lambda x: ','.join(x))df[['id', 'append']].to_csv(path, index=False, encoding='utf-8')rd_df = pd.read_csv(path, encoding='utf-8')rd_df['tags'] = rd_df['append'].apply(lambda x: x.split(','))print(rd_df['tags'])
csv文件內容:
id,append
1,"tag1,tag2"
2,tag3
3,"tag4,tag5"
注意這里自動加入了雙引號
文本限定符
,因為連接字符為逗號和csv分割符號一致,使用雙引號限定符避免因為逗號問題破壞csv結構.
程序輸出結果:
0 [tag1, tag2]
1 [tag3]
2 [tag4, tag5]
這種方法只能正對簡單的字符串列表,且列表中每一個元素字符串不能存再鏈接字符,不然讀取的數據split后就錯誤
所以這種方法只能在你確定了列表中元素字符串都不可能有用于連接的字符時,才使用.總之,此方法也有其局限性.
json.dumps序列化存儲以及json.loads反序列化讀取
這是目前最好的處理方法,將列表使用json.dumps
方法序列化為json字符串存儲,讀取的時候反序列化成列表即可:
def json_write_read():path = Path(__file__).parent.joinpath('json.csv')df = pd.DataFrame({'id': [1,2,3],'tags': [['tag1', 'tag2'], ['tag3'], ['tag4', 'tag5']]})df['json'] = df['tags'].apply(json.dumps)df[['id', 'json']].to_csv(path, index=False, encoding='utf-8')rd_df = pd.read_csv(path, encoding='utf-8')rd_df['tags'] = rd_df['json'].apply(json.loads)print(rd_df['tags'])print(rd_df['tags'][0])
csv文本內容:
id,json
1,"[""tag1"", ""tag2""]"
2,"[""tag3""]"
3,"[""tag4"", ""tag5""]"
非常標準的list字符串存csv
程序輸出結果
0 [tag1, tag2]
1 [tag3]
2 [tag4, tag5]
Name: tags, dtype: object
此方法還可以用來存儲以及讀取向兩數據,如下例子處理向量數據的讀寫問題
def vec_write_read():path = Path(__file__).parent.joinpath('vec.csv')df = pd.DataFrame({'id': [1,2,3],'vec': [[1, 2, 3], [2, 0, 1], [1, 1, 2]]})df['vec_s'] = df['vec'].apply(json.dumps)df[['id', 'vec_s']].to_csv(path, index=False)rd_df = pd.read_csv(path)rd_df['vec'] = rd_df['vec_s'].apply(json.loads)print(rd_df['vec'])
csv文件內容:
id,vec_s
1,"[1, 2, 3]"
2,"[2, 0, 1]"
3,"[1, 1, 2]"
輸出結果:
0 [1, 2, 3]
1 [2, 0, 1]
2 [1, 1, 2]
Name: vec, dtype: object
如果這個場景還在用第二種join方式轉成字符串還需要把每個維度數值轉為字符串才能join,實現起來就不太合適了.
總結
所以pandas里面list數據列存csv最佳做法還是將該列數據json.dumps成json字符串保存,讀取的時候使用json.loads還原