如何使用 pandas 将一列 csv 读取为 dtype 列表?
Posted
技术标签:
【中文标题】如何使用 pandas 将一列 csv 读取为 dtype 列表?【英文标题】:How to read a column of csv as dtype list using pandas? 【发布时间】:2015-12-20 23:19:45 【问题描述】:我有一个包含 3 列的 csv 文件,其中第 3 列的每一行都有其中的值列表。从下面的表结构可以看出
Col1,Col2,Col3
1,a1,"['Proj1', 'Proj2']"
2,a2,"['Proj3', 'Proj2']"
3,a3,"['Proj4', 'Proj1']"
4,a4,"['Proj3', 'Proj4']"
5,a5,"['Proj5', 'Proj2']"
每当我尝试读取此 csv 时,Col3 都会被读取为 str 对象而不是列表。我试图将该列的 dtype 更改为列出,但得到“属性错误”,如下所示
df = pd.read_csv("inputfile.csv")
df.Col3.dtype = list
AttributeError Traceback (most recent call last)
<ipython-input-19-6f9ec76b1b30> in <module>()
----> 1 df.Col3.dtype = list
C:\Python27\lib\site-packages\pandas\core\generic.pyc in __setattr__(self, name, value)
1953 object.__setattr__(self, name, value)
1954 except (AttributeError, TypeError):
-> 1955 object.__setattr__(self, name, value)
1956
1957 #----------------------------------------------------------------------
AttributeError: 无法设置属性
如果你能指导我如何去做,那就太好了。
【问题讨论】:
你能给我们看一个你的csv的例子吗(不是图片),复制粘贴你的csv的前几行。 标准警告:pandas 并不真正支持非标量值。您可以使用它们,因为它们有时在中间步骤中很方便,但使用它们很不方便,而且在不久的将来也不会改变。 你想对这些值做什么? @AnandSKumar 从我的 csv 复制粘贴的值 @PadraicCunningham 不,最终值将是一个字符串。我的需求 PFB 示例说明 Input Row:1,a1,"['Proj1', 'Proj2']" Output Rows: 1,a1,"Proj1" 1,a1,"Proj2" 【参考方案1】:你可以使用 ast 库:
from ast import literal_eval
df.Col3 = df.Col3.apply(literal_eval)
print(df.Col3[0][0])
Proj1
您也可以在从 csv 创建数据框时使用converters
:
df = pd.read_csv("in.csv",converters="Col3": literal_eval)
如果您确定所有字符串的格式都相同,那么剥离和拆分会快很多:
df = pd.read_csv("in.csv",converters="Col3": lambda x: x.strip("[]").split(", "))
但你最终会得到用引号括起来的字符串
【讨论】:
尝试执行此操作时返回语法错误。我的字符串是 '[whatever.com/extension]' 就像@5norre 下面的回答一样,当输入为[]
时,lambda 函数在返回['']
的空列表上失败。
实际上花了 30 分钟在谷歌上搜索这个简单的答案。【参考方案2】:
为 Cunninghams 答案添加替换:
df = pd.read_csv("in.csv",converters="Col3": lambda x: x.strip("[]").replace("'","").split(", "))
另见pandas - convert string into list of strings
【讨论】:
这是一个简洁的解决方案,但它不处理空字符串,lambda 为输入['']
提供 []
【参考方案3】:
我有一个不同的方法,它可以用于其他数据类型的字符串表示,除了列表。
您可以使用 json 库并将 json.loads() 应用于所需的列。例如
import json
df.my_column = df.my_column.apply(json.loads)
但是,要使其正常工作,您的输入字符串必须用双引号括起来。
【讨论】:
【参考方案4】:如果您必须解析没有引号的字符串列表,@Padraic Cunningham 的答案将不起作用。例如,literal_eval
将成功解析 "['a', 'b', 'c']"
,但不会成功解析 "[a, b, c]"
。要加载这样的字符串,请使用 PyYAML 库。
import io
import pandas as pd
data = '''
A,B,C
"[1, 2, 3]",True,"[a, b, c]"
"[4, 5, 6]",False,"[d, e, f]"
'''
df = pd.read_csv(io.StringIO(data), sep=',')
df
A B C
0 [1, 2, 3] True [a, b, c]
1 [4, 5, 6] False [d, e, f]
df['C'].tolist()
# ['[a, b, c]', '[d, e, f]']
import yaml
df[['A', 'C']] = df[['A', 'C']].applymap(yaml.safe_load)
df['C'].tolist()
# [['a', 'b', 'c'], ['d', 'e', 'f']]
yaml
可以使用pip install pyyaml
安装。
【讨论】:
【参考方案5】:如果您可以选择写入文件 -
您可以使用 pd.to_parquet
和 pd.read_parquet
(而不是 csv)。
它将正确解析此列。
【讨论】:
这太棒了。这使我免于使用许多其他非优雅的方式来保存和读取具有此类列的数据帧。【参考方案6】:csv 中类似数组的列的另一种解决方案:
df = pd.read_csv("inputfile.csv")
df["Col3"] = df["Col3"].fillna("[]").apply(lambda x: eval(x))
【讨论】:
以上是关于如何使用 pandas 将一列 csv 读取为 dtype 列表?的主要内容,如果未能解决你的问题,请参考以下文章
Pandas: 如何将一列中的文本拆分为多行? | Python