【问题标题】:Pandas read_csv dtype read all columns but few as stringPandas read_csv dtype 读取所有列,但很少作为字符串读取
【发布时间】:2018-09-16 00:27:38
【问题描述】:

我正在使用 Pandas 读取一堆 CSV。将选项 json 传递给 dtype 参数以告诉 pandas 将哪些列作为字符串而不是默认值读取:

dtype_dic= { 'service_id':str, 'end_date':str, ... }
feedArray = pd.read_csv(feedfile , dtype = dtype_dic)

在我的场景中,所有除少数特定列之外的列将被读取为字符串。因此,我不想在dtype_dic 中将几列定义为str,而是将我选择的少数设置为int 或float。有没有办法做到这一点?

这是一个循环遍历具有不同列的各种 CSV,因此在将整个 csv 读取为字符串 (dtype=str) 后直接进行列转换并不容易,因为我不会立即知道 csv 具有哪些列。 (我宁愿花精力定义 dtype json 中的所有列!)

编辑:但是,如果有一种方法可以处理要转换为数字的列名列表,而不会在该列不存在于该 csv 中时出错,那么是的,如果没有其他方法,那将是一个有效的解决方案在 csv 读取阶段执行此操作的方法。

注意:这听起来 like a previously asked question 但那里的答案走了一条非常不同的路径(与布尔相关),不适用于这个问题。请不要标记为重复!

【问题讨论】:

    标签: python pandas csv


    【解决方案1】:

    您可以执行以下操作:

    pd.read_csv(self._LOCAL_FILE_PATH,
                index_col=0,
                 encoding="utf-8",
                 dtype={
                        'customer_id': 'int32',
                        'product_id': 'int32',
                        'subcategory_id': 'int16',
                        'category_id': 'int16',
                        'gender': 'int8',
                        'views': 'int8',
                        'purchased': 'int8',
                        'added': 'int8',
                        'time_on_page': 'float16',
                     })
    

    【讨论】:

      【解决方案2】:

      我最近遇到了同样的问题,虽然我只有一个 csv 文件,所以我不需要循环文件。我认为这个解决方案也可以改编成循环。

      在这里,我提出了一个我使用的解决方案。 Pandas 的read_csv 有一个名为converters 的参数会覆盖dtype,因此您可以利用此功能。

      示例代码如下: 假设我们的data.csv 文件包含除AB 之外的所有float64 列,它们是字符串列。您可以使用以下方式阅读此文件:

      df = pd.read_csv('data.csv', dtype = 'float64', converters = {'A': str, 'B': str})  
      

      代码给出警告,即转换器会覆盖 A 和 B 这两列的 dtype,结果符合预期。

      关于循环多个 c​​sv 文件,所有需要做的就是找出哪些列将是例外放入转换器。如果文件具有类似的列名模式,这很容易,否则会变得乏味。

      【讨论】:

      • 您可以只为一列或多列指定转换器,而不为其他列指定 dtype。当您只需要为其指定格式的几列,并且您不想像上面的答案中那样为所有列指定格式时,它非常有用。
      【解决方案3】:

      编辑 - 抱歉,我误读了您的问题。更新了我的答案。

      您可以将整个 csv 读取为字符串,然后将所需的列转换为其他类型,如下所示:

      df = pd.read_csv('/path/to/file.csv', dtype=str)
      # example df; yours will be from pd.read_csv() above
      df = pd.DataFrame({'A': ['1', '3', '5'], 'B': ['2', '4', '6'], 'C': ['x', 'y', 'z']})
      types_dict = {'A': int, 'B': float}
      for col, col_type in types_dict.items():
          df[col] = df[col].astype(col_type)
      

      另一种方法,如果您真的想在读取文件时为所有列指定正确的类型并且之后不更改它们:仅读取列名(无行),然后使用这些来填写应该是哪些列字符串

      col_names = pd.read_csv('file.csv', nrows=0).columns
      types_dict = {'A': int, 'B': float}
      types_dict.update({col: str for col in col_names if col not in types_dict})
      pd.read_csv('file.csv', dtype=types_dict)
      

      【讨论】:

      • 1.如果该 CSV 中不存在上述列,这将出错。请看问题。 2.我想默认将所有列转换为字符串,除了一些选择的列。请看问题。
      • 太棒了!抱歉,当时我没有看到您的更新。有趣的是,我想如果有任何变化,我会收到一些警报。我特别喜欢第二种方法.. 两全其美。
      • 当您想在 read_csv 函数中指定小数分隔符时,这将不起作用。它会将这些数字转换为带有错误小数分隔符的 str ,此后您将无法直接将其转换为浮点数。
      • 你可以先做str.replace 转换成"."作为小数分隔符或编写自己的类型转换函数,而不是使用float/int(例如lambda x: float(x.replace(",", ".")))。后者可能更慢
      • 实际上,如果您在这里使用第二种方法,我看不出有任何理由指定小数分隔符不能直接工作;上面的评论只对使用的第一种方法很重要。
      猜你喜欢
      • 1970-01-01
      • 2016-11-02
      • 1970-01-01
      • 2018-08-28
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      • 2013-03-18
      • 2018-03-23
      相关资源
      最近更新 更多