【问题标题】:Read specific columns from a csv file with csv module?使用 csv 模块从 csv 文件中读取特定列?
【发布时间】:2013-05-06 09:29:24
【问题描述】:

我正在尝试解析 csv 文件并仅从特定列中提取数据。

示例 csv:

ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
10 | C... | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |

我正在尝试仅捕获特定列,例如 IDNameZipPhone

我看过的代码让我相信我可以通过其对应的数字来调用特定的列,所以即:Name 将对应于 2 并使用 row[2] 遍历每一行将产生所有第 2 列中的项目。只有它没有。

这是我到目前为止所做的:

import sys, argparse, csv
from settings import *

# command arguments
parser = argparse.ArgumentParser(description='csv to postgres',\
 fromfile_prefix_chars="@" )
parser.add_argument('file', help='csv file to import', action='store')
args = parser.parse_args()
csv_file = args.file

# open csv file
with open(csv_file, 'rb') as csvfile:

    # get number of columns
    for line in csvfile.readlines():
        array = line.split(',')
        first_item = array[0]

    num_columns = len(array)
    csvfile.seek(0)

    reader = csv.reader(csvfile, delimiter=' ')
        included_cols = [1, 2, 6, 7]

    for row in reader:
            content = list(row[i] for i in included_cols)
            print content

我希望这只会打印出我想要的每一行的特定列,除非它没有,我只得到最后一列。

【问题讨论】:

  • 为什么将'rb' 标记为open()?不应该是简单的r吗?
  • @Elazar:在 Python 2(OP 正在使用)中,"rb" 适合传递给csv.reader
  • 为什么您的示例 CSV 文件将竖线字符显示为分隔符,而您的示例代码使用空格?
  • @KellyS.French 我认为这将有助于可视化数据以解决这个问题。

标签: python csv


【解决方案1】:

从这段代码中获取最后一列的唯一方法是,如果您不将打印语句包含在您的for 循环中。

这很可能是您的代码的结尾:

for row in reader:
    content = list(row[i] for i in included_cols)
print content

你希望它是这样的:

for row in reader:
        content = list(row[i] for i in included_cols)
        print content

现在我们已经解决了您的错误,我想借此机会向您介绍pandas 模块。

Pandas 非常适合处理 csv 文件,您只需以下代码即可读取 csv 并将整列保存到变量中:

import pandas as pd
df = pd.read_csv(csv_file)
saved_column = df.column_name #you can also use df['column_name']

因此,如果您想将列 Names 中的所有信息保存到一个变量中,您只需这样做:

names = df.Names

这是一个很棒的模块,我建议您研究一下。如果由于某种原因您的打印语句在for 循环中并且它仍然只打印出最后一列,这不应该发生,但如果我的假设是错误的,请告诉我。您发布的代码有很多缩进错误,因此很难知道应该在哪里。希望这对您有所帮助!

【讨论】:

  • 是否可以从查询中删除索引号? @Ryan Saxe
  • 是的,只需在 for 循环中遍历它。
【解决方案2】:
import csv
from collections import defaultdict

columns = defaultdict(list) # each value in each column is appended to a list

with open('file.txt') as f:
    reader = csv.DictReader(f) # read rows into a dictionary format
    for row in reader: # read a row as {column1: value1, column2: value2,...}
        for (k,v) in row.items(): # go over each column name and value 
            columns[k].append(v) # append the value into the appropriate list
                                 # based on column name k

print(columns['name'])
print(columns['phone'])
print(columns['street'])

像这样的文件

name,phone,street
Bob,0893,32 Silly
James,000,400 McHilly
Smithers,4442,23 Looped St.

会输出

>>> 
['Bob', 'James', 'Smithers']
['0893', '000', '4442']
['32 Silly', '400 McHilly', '23 Looped St.']

或者,如果您想要列的数字索引:

with open('file.txt') as f:
    reader = csv.reader(f)
    reader.next()
    for row in reader:
        for (i,v) in enumerate(row):
            columns[i].append(v)
print(columns[0])

>>> 
['Bob', 'James', 'Smithers']

要更改分隔符,请将delimiter=" " 添加到适当的实例化中,即reader = csv.reader(f,delimiter=" ")

【讨论】:

    【解决方案3】:

    使用pandas:

    import pandas as pd
    my_csv = pd.read_csv(filename)
    column = my_csv.column_name
    # you can also use my_csv['column_name']
    

    在解析时丢弃不需要的列:

    my_filtered_csv = pd.read_csv(filename, usecols=['col1', 'col3', 'col7'])
    

    附:我只是以简单的方式汇总其他人所说的话。实际答案取自herehere

    【讨论】:

    • 我认为 Pandas 是一个完全可以接受的解决方案。我经常使用 Pandas,非常喜欢这个库,但是这个问题专门引用了 CSV 模块。
    • @frankV 嗯,标题、标签和第一段并没有以任何方式禁止熊猫,AFAI 可以看到。实际上,我只是希望为这里已经提出的答案添加一个更简单的答案(其他答案也使用熊猫)。
    【解决方案4】:

    您可以使用numpy.loadtext(filename)。例如,如果这是您的数据库.csv:

    ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
    10 | Adam | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
    10 | Carl | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
    10 | Adolf | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
    10 | Den | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
    

    而你想要Name 列:

    import numpy as np 
    b=np.loadtxt(r'filepath\name.csv',dtype=str,delimiter='|',skiprows=1,usecols=(1,))
    
    >>> b
    array([' Adam ', ' Carl ', ' Adolf ', ' Den '], 
          dtype='|S7')
    

    您可以更轻松地使用genfromtext

    b = np.genfromtxt(r'filepath\name.csv', delimiter='|', names=True,dtype=None)
    >>> b['Name']
    array([' Adam ', ' Carl ', ' Adolf ', ' Den '], 
          dtype='|S7')
    

    【讨论】:

    • @G 'filepath\name.csv' 旁边是否有一个 r?
    【解决方案5】:

    使用pandas,您可以使用read_csvusecols 参数:

    df = pd.read_csv(filename, usecols=['col1', 'col3', 'col7'])
    

    例子:

    import pandas as pd
    import io
    
    s = '''
    total_bill,tip,sex,smoker,day,time,size
    16.99,1.01,Female,No,Sun,Dinner,2
    10.34,1.66,Male,No,Sun,Dinner,3
    21.01,3.5,Male,No,Sun,Dinner,3
    '''
    
    df = pd.read_csv(io.StringIO(s), usecols=['total_bill', 'day', 'size'])
    print(df)
    
       total_bill  day  size
    0       16.99  Sun     2
    1       10.34  Sun     3
    2       21.01  Sun     3
    

    【讨论】:

      【解决方案6】:

      上下文:对于这种类型的工作,您应该使用令人惊叹的 python petl 库。这将为您节省大量工作和使用标准 csv 模块“手动”执行操作的潜在挫败感。 AFAIK,唯一仍在使用 csv 模块的人是那些尚未发现更好的处理表格数据(熊猫、petl 等)的工具的人,这很好,但如果您打算在你的职业生涯来自各种奇怪的来源,学习像 petl 这样的东西是你可以做出的最好的投资之一。完成 pip install petl 后,只需 30 分钟即可开始使用。文档非常好。

      答案:假设您在 csv 文件中有第一个表(您也可以使用 petl 直接从数据库加载)。然后,您只需加载它并执行以下操作。

      from petl import fromcsv, look, cut, tocsv 
      
      #Load the table
      table1 = fromcsv('table1.csv')
      # Alter the colums
      table2 = cut(table1, 'Song_Name','Artist_ID')
      #have a quick look to make sure things are ok. Prints a nicely formatted table to your console
      print look(table2)
      # Save to new file
      tocsv(table2, 'new.csv')
      

      【讨论】:

        【解决方案7】:

        我认为有一个更简单的方法

        import pandas as pd
        
        dataset = pd.read_csv('table1.csv')
        ftCol = dataset.iloc[:, 0].values
        

        所以这里iloc[:, 0]: 表示所有值,0 表示列的位置。 在下面的示例中,ID 将被选中

        ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
        10 | C... | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
        

        【讨论】:

          【解决方案8】:
          import pandas as pd 
          csv_file = pd.read_csv("file.csv") 
          column_val_list = csv_file.column_name._ndarray_values
          

          【讨论】:

          • 你必须先pip install pandas
          【解决方案9】:

          由于您可以索引和子集 pandas 数据框,从 csv 文件中提取单个列到变量中的一种非常简单的方法是:

          myVar = pd.read_csv('YourPath', sep = ",")['ColumnName']
          

          需要考虑的几点:

          上面的 sn-p 将产生一个熊猫 Series 而不是 dataframe。 如果速度是一个问题,ayhan 与usecols 的建议也会更快。 在 2122 KB 大小的 csv 文件上使用 %timeit 测试这两种不同的方法会产生 22.8 ms 用于 usecols 方法,53 ms 用于我建议的方法。

          别忘了import pandas as pd

          【讨论】:

            【解决方案10】:

            如果您需要单独处理列,我喜欢使用zip(*iterable) 模式解构列(实际上是“解压缩”)。所以对于你的例子:

            ids, names, zips, phones = zip(*(
              (row[1], row[2], row[6], row[7])
              for row in reader
            ))
            

            【讨论】:

              【解决方案11】:
              SAMPLE.CSV
              a, 1, +
              b, 2, -
              c, 3, *
              d, 4, /
              column_names = ["Letter", "Number", "Symbol"]
              df = pd.read_csv("sample.csv", names=column_names)
              print(df)
              OUTPUT
                Letter  Number Symbol
              0      a       1      +
              1      b       2      -
              2      c       3      *
              3      d       4      /
              
              letters = df.Letter.to_list()
              print(letters)
              OUTPUT
              ['a', 'b', 'c', 'd']
              

              【讨论】:

                【解决方案12】:
                import pandas as pd
                
                dataset = pd.read_csv('Train.csv')
                X = dataset.iloc[:, 1:-1].values
                y = dataset.iloc[:, -1].values
                
                • X 是一堆列,如果您想阅读更多的列,请使用它
                • y是单列,用它读一列
                • [:, 1:-1][row_index : to_row_index, column_index : to_column_index]

                【讨论】:

                  【解决方案13】:

                  要获取 列名,而不是使用 readlines(),最好使用 readline() 来避免循环和读取完整的文件并存储它在数组中。

                  with open(csv_file, 'rb') as csvfile:
                  
                      # get number of columns
                  
                      line = csvfile.readline()
                  
                      first_item = line.split(',')
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2017-12-07
                    • 2013-05-20
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多