2014-12-02 93 views
1

我試圖讀取一個csv文件並從中提取所需的數據。我的代碼如下所示。閱讀csv文件時跳過第一列Python

import csv 
file = "sample.csv" 
def get_values_flexibly(file, keyword): 
    def process(func): 
     return set([func(cell)] + [func(row[index]) for row in reader]) 

    with open(file, 'r') as f: 
     reader = csv.reader(f) 
     first_row = reader.next() 
     if keyword in first_row: 
      return str(list(set([row[first_row.index(keyword)] for row in reader]))) 
     for index, cell in enumerate(reader.next()): 
      if cell.endswith(' ' + keyword): 
       return str(list(set(process(lambda cell: cell[:-len(keyword) - 1])))) 
      elif cell.split(':')[0].strip() == keyword: 
       return str(list(set(process(lambda cell: cell.split(':')[1].strip())))) 
print get_values_flexibly(file, 'data') 

其中sample.csv看起來像下面

sample.csv

h1,h2,h3 
a data,data: abc,tr 
b data,vf data, gh 
k data,grt data, ph 

我想從輸出排除第一列。我目前的輸出是['a','k','b'],但我希望它是['abc', 'vf', 'grt']。我怎樣才能實現這一點使用CSV閱讀器?

編輯 - 我有多個文件。每個文件可能有不同的標題和列數也不相同。我想要一個適用於所有文件的腳本。另外,第一列的標題總是相同的,例如「sample_column」。我想從標題爲「sample_column」的列中跳過數據。

+0

是您的關鍵字總是要'data'? – BorrajaX 2014-12-02 22:28:50

+0

@BorrajaX號不同。 – abn 2014-12-02 22:29:22

+0

你可以(或者介意)使用正則表達式來刪除你的單元格的「關鍵字」塊? – BorrajaX 2014-12-02 22:32:23

回答

0

好了,所以去除data(或任何的關鍵字)可以用正則表達式完成(這是不是真正的問題,但MEH範圍...)

關於正則表達式:

假設您的關鍵字是data,對不對?您可以使用此:(?:data)*\W*(?P<juicy_data>\w+)\W*(?:data)*如果您的關鍵字是別的東西,你可以改變兩個data串在正則表達式中的任何其他值keyword包含...

可以在www.pythonregex.comwww.debuggex.com

在線測試正則表達式

正則表達式基本上是這樣說的:查找0個或更多個data字符串,但是(如果您發現的話)不要對它們做任何事情。不要將它們添加到匹配組的列表中,不要顯示它們......沒有,只是匹配它們,但放棄它。之後,查找零個或多個非單詞字符(任何不是字母或數字......以防萬一有data:或之後的空格或data--> ...... \W刪除所有非字符字符,在data之後出現的字母數字字符)然後,您會到達您的juicy_data這是可以在「常規」字(任何字母數字字符)中找到的一個或多個字符。然後,爲了防止後面有data,請按照與第一個data組完成的相同的操作。只要匹配並刪除它。

現在,要刪除第一列:您可以使用這樣一個事實,即一個csv.reader本身就是一個迭代器。當你迭代它時(如下面的代碼所做的那樣),它會給你一個包含一行中所有列的列表。它爲您提供所有行的list這一事實對您的情況非常有用:您只需收集所述row的第一項,因爲這是您關心的列(您不需要row[0],也不需要row[1:]

所以這裏有雲:

import csv 
import re 

def get_values_flexibly(csv_path, keyword): 
    def process(func): 
     return set([func(cell)] + [func(row[index]) for row in reader]) 
    # Start fo real! 
    kwd_remover = re.compile(
     r'(?:{kw})*\W*(?P<juicy_data>\w+)\W*(?:{kw})*'.format(kw=keyword) 
    ) 
    result = [] 
    with open(csv_path, 'r') as f: 
     reader = csv.reader(f) 
     first_row = [kwd_remover.findall(cell)[0] for cell in reader.next()] 
     print "Cleaned first_row: %s" % first_row 
     for index, row in enumerate(reader): 
      print "Before cleaning: %s" % row 
      cleaned_row = [kwd_remover.findall(cell)[0] for cell in row] 
      result.append(cleaned_row[1]) 
      print "After cleaning: %s" % cleaned_row 
    return result 

print "Result: %s" % get_values_flexibly("sample.csv", 'data') 

輸出:

Cleaned first_row: ['h1', 'h2', 'h3'] 
Before cleaning: ['a data', 'data: abc', 'tr'] 
After cleaning: ['a', 'abc', 'tr'] 
Before cleaning: ['b data', 'vf data', ' gh'] 
After cleaning: ['b', 'vf', 'gh'] 
Before cleaning: ['k data', 'grt data', ' ph'] 
After cleaning: ['k', 'grt', 'ph'] 
Result: ['abc', 'vf', 'grt'] 
+0

非常感謝,無論是代碼和解釋。 – abn 2014-12-02 23:41:24

+0

當然!感謝您考慮*選定的答案*。如果您對代碼有疑問,請告訴我。我可以編輯答案來添加一些說明。這可以幫助其他人在未來找到答案(如果你有問題,別人也有機會獲得答案) – BorrajaX 2014-12-02 23:43:15

1

您可以使用字典讀者:

data = {'h1':[], 'h2':[], 'h3':[]} 

h = ['h1', 'h2', 'h3'] 
csvfile = open(dir) 
reader = DictReader(csvfile) 
for line in reader: 
    data['h1'].append(line[h[0]][2:]) 
    data['h2'].append(line[h[1]][2:]) # Use indexing to get the bits you want 
    data['h3'].append(line[h[2]]) 
+0

謝謝你的迴應。我的錯。我沒有正確地問這個問題。我有多個文件,每個文件可能有不同的標題和列數不同。我想要一個適用於所有文件的腳本。 – abn 2014-12-02 22:40:31

+0

您可以使用第一行來製作數據字典,然後將數據添加到它,這可能會使問題更簡單... – kezzos 2014-12-02 22:48:44