【发布时间】:2019-11-20 08:25:00
【问题描述】:
更新:
TomNash 的回答解决了所提出的问题。但是,尝试在我的实际问题中使用它会导致引用列名出现问题、缺少数据时出现问题等。为了避免这种情况,我在 cmets 中使用 CJR 的建议来简单地腌制我的 DataFrame。
下面的原始问题:
我在内存中有一个 Panda 的 DataFrame。我希望能够将其写入文件(使用to_csv),然后使用read_csv 将结果读入新的DataFrame。我希望原始 DataFrame 和新的“来自文件 DataFrame”具有相同的数据类型。
我试图通过为to_csv 和read_csv 使用quoting 和quotechar 参数来实现此功能。但是,这似乎并不能解决问题。
我知道对于read_csv,dtype 参数可用于强制数据类型,但这对我的用例(大量用于回归测试的自动生成文件)来说并不实用。
下面的完整示例。
tmp.py:
import pandas as pd
from csv import QUOTE_NONNUMERIC
import sys
print('Python version information:')
print(sys.version)
print('Pandas version information:')
print(pd.__version__)
df1 = pd.DataFrame([['A', '100', 100], ['B', '200', 200]])
print('df1:')
print(df1.info())
df1.to_csv('tmp.csv', index=False, quoting=QUOTE_NONNUMERIC,
quotechar='"')
df2 = pd.read_csv('tmp.csv', quoting=QUOTE_NONNUMERIC, quotechar='"')
print('df2:')
print(df2.info())
运行tmp.py的输出:
Python version information:
3.7.3 (default, Jun 11 2019, 01:11:15)
[GCC 6.3.0 20170516]
Pandas version information:
0.24.2
df1:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2 entries, 0 to 1
Data columns (total 3 columns):
0 2 non-null object
1 2 non-null object
2 2 non-null int64
dtypes: int64(1), object(2)
memory usage: 128.0+ bytes
None
df2:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2 entries, 0 to 1
Data columns (total 3 columns):
0 2 non-null object
1 2 non-null float64
2 2 non-null float64
dtypes: float64(2), object(1)
memory usage: 128.0+ bytes
None
- 第 1 列:正如预期的那样,两个 DataFrame 的 dtype 均为
object。 - 第 2 列:意外行为。对于
df1,dtype 是object,而对于df2,dtype 是float64。 - 第 3 列:预期行为。
df1的数据类型为int64,而df2的数据类型为float64。正如csv module 所述,csv.QUOTE_NONNUMERIC“指示读者将所有未引用的字段转换为浮点类型。”
tmp.csv的内容如下。请注意,第二列被引用,所以我希望read_csv 给我一个对象。
tmp.csv:
0,1,2
"A","100",100
"B","200",200
【问题讨论】:
-
我不确定您是否可以从 CSV 轻松获得所需的行为。使用
cPickle或dill序列化数据框将保留该信息 - 如果您只是想针对一堆对象进行回归测试,这可能比为pd.read_csv()编写自己的转换器更容易。 -
@CJR - 感谢您的意见!我一定会考虑的。酸洗方法的缺点是版本控制和可读性:在我的存储库中有纯文本文件很好 a) 当预期结果发生变化时能够
diff文件 b) 能够用文本破解打开文件快速浏览的编辑器或电子表格程序。 -
@TomNash -
QUOTE_NONE没有做我想做的事。不同之处在于df2第 2 列和第 3 列的 dtype 均为int64(与float64相对)。 -
我认为问题在于
df1.iloc[:,2]中没有任何float64值,只有int64。对于任何数字,read_csv的行为将直接转换为float64。下面的解决方案将保留读/写之间的数据类型,我相信这是你想要的。 -
@TomNash - 您的解决方案如下解决了我的问题。我不得不搞乱我现在引用的所有列名,并用
object的dtype 替换所有列上的引号字符,但我可以编写一个简单的包装器来处理这个问题。由于它只是用于测试,因此我不会对进行所有这些替换所带来的性能影响感到不安。
标签: python python-3.x pandas csv dataframe