列位置影响pandas.read_csv()中的布尔识别

yshpjwxd  于 2023-03-28  发布在  其他
关注(0)|答案(2)|浏览(107)

我有制表符分隔值的文件看起来像这样(注意:唯一的区别是列的顺序):
first_col.tsv

name    bool_col    float_col
ist_true    true    1
also_true   1   2
is_false    false   3
also_false  0   4
is_empty        5

last_col.tsv

name    float_col   bool_col
ist_true    1   true
also_true   2   1
is_false    3   false
also_false  4   0
is_empty    5

如果我现在用以下命令读取这两个文件:

df = pd.read_csv(
    <filename>,
    sep="\t|,|;",
    true_values=["1","True","true","yes"],
    false_values=["0","False","false","no"]
).fillna({"bool_col": False}).set_index('name')
print(df)
print(df.dtypes)

两个文件得到不同的结果:
first_col.tsv

bool_col  float_col
name                           
ist_true        True          1
also_true       True          2
is_false       False          3
also_false     False          4
is_empty       False          5

bool_col      bool
float_col    int64
dtype: object

last_col.tsv

float_col bool_col
name                          
ist_true            1     true
also_true           2        1
is_false            3    false
also_false          4        0
is_empty            5    False

float_col     int64
bool_col     object
dtype: object

有谁能解释一下为什么会发生这种情况,我能做些什么来总是得到预期的结果-〉一个完整的布尔列?
我已经尝试了相同的逗号分隔文件:这里的行为与预期的一样,两种情况都有一个完整的布尔列。

p8ekf7hl

p8ekf7hl1#

它不起作用,因为您的两个文件之间存在差异:列顺序。在第一个TSV文件中,空单元格被定义为NaN,而不是在第二个TSV文件中,空单元格被设置为None,这是不同的。您可以将None追加到false_values的列表中

params = {'sep': "\t|,|;", 'engine': 'python',
          'true_values': ["1","True","true","yes"],
          'false_values': ["0","False","false","no"]}

>>> pd.read_csv('first_col.tsv', **params)
         name bool_col  float_col
0    ist_true     True          1
1   also_true     True          2
2    is_false    False          3
3  also_false    False          4
4    is_empty      NaN          5

>>> pd.read_csv('last_col.tsv', **params)
         name  float_col bool_col
0    ist_true          1     true
1   also_true          2        1
2    is_false          3    false
3  also_false          4        0
4    is_empty          5     None  # <- None and not NaN

现在修改false_values

params = {'sep': "\t|,|;", 'engine': 'python',
          'true_values': ["1","True","true","yes"],
          'false_values': ["0","False","false","no",None]}  # <- HERE

>>> pd.read_csv('last_col.tsv', **params)
         name  float_col  bool_col
0    ist_true          1      True
1   also_true          2      True
2    is_false          3     False
3  also_false          4     False
4    is_empty          5     False

您也可以将NaN追加到false_values列表中:

params = {'sep': "\t|,|;", 'engine': 'python',
          'true_values': ["1","True","true","yes"],
          'false_values': ["0","False","false","no",None,np.nan]}  # <- HERE

>>> pd.read_csv('first_col.tsv', **params)
         name  bool_col  float_col
0    ist_true      True          1
1   also_true      True          2
2    is_false     False          3
3  also_false     False          4
4    is_empty     False          5
bf1o4zei

bf1o4zei2#

这个问题不仅仅是由于read_csv,而是由于布尔值和数字不能共享除object之外的公共类型:

pd.Series([1, True]).dtype
# dtype('O')

导入后需要显式Map值并转换为boolean `

mapper = {"1": 1, "True": 1, "true": 1, "yes": 1, "0": 0, "False": 0, "false": 0, "no": 0, "": 0}

df = pd.read_csv(
    filename,
    sep="\t|,|;",
    engine='python',
).replace({"bool_col": mapper}).astype({'bool_col': bool}).set_index('name')

print(df)
print(df.dtypes)

或者:

df = pd.read_csv(
    filename,
    sep="\t|,|;",
    engine='python',
).assign(bool_col=lambda d: d['bool_col'].isin(true_values))

相关问题