2014-09-22 126 views
1

我想按列排序csv文件。該文件有很多欄目,看起來像:用python排序csv文件

湯姆,01AA01,234.56,334

愛麗絲,01AS01,546.09,3434.3

山姆,01NA01,4574.3,65.45

喜悅,01BA01, 2897.03,455

帕姆,01MA01,434.034,454

約翰,01AA02,343,24

愛麗絲,01AS02,454,454.54

湯姆,02BA01,3434,3454.2

它持續約20列和250列。

我希望它由第二列進行排序和按字母順序排列爲AAASBA在第二部分,和數值爲第三部分「01」,「02」,「03」,和數值爲第一部分'01','02','03'。然後從這種類型創建一個新的CSV文件。他們通常只有6個字符長,其他人看起來像'02BAA','01MAA','02NAA'等等。

那麼到底它會希望像這樣的第2列。

01AA01 
01AS01 
01BA01 
01MA01 
01NA01 
01AA02 
01AS02 
02BA01 

我是新來的編碼,而不是很清楚如何去這樣做。先謝謝你。

+4

就像一個註釋,如果所有的列值看起來像那樣,那麼排序將保持你想要的順序。例如,對該列進行排序會自動滿足您的所有條件。因此,您可以簡化您的問題以按列對CSV進行排序,因爲這裏不需要特殊的排序條件。 – Tommy 2014-09-22 01:42:19

+0

@Tommy - 我不明白...你是說因爲樣本已經按OP的方式排序,所以它們都必須按照這種方式排序? – tdelaney 2014-09-22 01:47:35

+0

@Tammy,你用什麼工具管理csv,csv模塊?當你想排序時它是在一個python列表中嗎? – tdelaney 2014-09-22 01:48:32

回答

1

默認排序順序爲ASCII字符串從Python的sorted功能lexicographic(或 'ASCIIbetical'):

>>> li=['1', '20', '100', '11'] 
>>> sorted(li) 
['1', '100', '11', '20'] 

相比時,這些列表值是整數整數大小:

>>> sorted(map(int, li)) 
[1, 11, 20, 100] 

即,人眼的字符串數量的大小與計算機眼睛的相同字符串的大小不同。 (寫在Codinghorror更廣泛)

要解決它,我們需要從數字中分離字母,並將數字轉換爲整數(或浮點數)。

最簡單的方法是用正則表達式捕獲所有數字,然後轉換爲整數,然後轉換爲所有字母。

此排序到你的目標:

li1='''\ 
01AA01 
01AS01 
01NA01 
01BA01 
01MA01 
01AA02 
01AS02 
02BA01'''.splitlines() 

tgt='''\ 
01AA01 
01AS01 
01BA01 
01MA01 
01NA01 
01AA02 
01AS02 
02BA01'''.splitlines() 


import re 

def kf(s): 
    nums=map(int, re.findall(r'(\d+)', s)) 
    lets=re.findall(r'([a-zA-Z]+)', s) 
    return nums+lets 

print tgt==sorted(li1, key=kf) 
# True 

或者一個行:

>>> tgt==sorted(li1, key=lambda s: map(int, re.findall(r'(\d+)', s))+re.findall(r'(\D+)', s)) 
True 

編輯基於評論

問題狀態的文本

我希望它在首節01,02,03 ...... 數字進行排序,然後按字母順序爲AA,AS,BA在第二部分,並且 數值再次爲第三部分。

但是,示例表明情況並非如此。

我們可以排序的基礎上(INT,字母,INT)與拆分模式:

>>> [re.split(r'(\D+)', e) for e in li1] 
[['01', 'AA', '01'], ['01', 'AS', '01'], ['01', 'NA', '01'], ['01', 'BA', '01'], ['01', 'MA', '01'], ['01', 'AA', '02'], ['01', 'AS', '02'], ['02', 'BA', '01']] 
>>> sorted(li1, key=lambda s: [int(e) if e.isdigit() else e for e in re.split(r'(\D+)', s)]) 
['01AA01', '01AA02', '01AS01', '01AS02', '01BA01', '01MA01', '01NA01', '02BA01'] 
#    ^^  ^^  etc '01AA02', before '01AS01' in the example 

通過檢查,張貼的例子的模式是(int, int, letters)可以在這裏看到:

>>> [map(int, re.findall(r'(\d+)', s))+re.findall(r'(\D+)', s) for s in li1] 
[[1, 1, 'AA'], [1, 1, 'AS'], [1, 1, 'NA'], [1, 1, 'BA'], [1, 1, 'MA'], [1, 2, 'AA'], [1, 2, 'AS'], [2, 1, 'BA']] 

如果TEXT是正確的,使用排序的分割形式我有;如果是正確的,使用nums+lets形式。

+0

這似乎按照第一,第三和第二部分進行排序。例如,「01AA01」將按鍵排序(1,1,「AA」)。 – monkut 2014-09-22 02:27:30

+0

這就是這個例子的排序方式。因此'01AS01'排序在'01AA02'之前 – dawg 2014-09-22 02:38:03

+0

您的權利!我正在脫離文本,這似乎意味着按第一,第二和第三組排序。 – monkut 2014-09-22 02:44:08

0

sorted()和列表的.sort()方法採用可選的key參數。

其中:

指定用於提取從每個列表元素的 對比密鑰一個參數的函數:鍵= str.lower。

換句話說,考慮到關鍵的參數解析和(你會寫)函數將返回給定對象的排序值。

因此,考慮到你的輸入,"01AS01",要分解成可以很容易地整理碎片。如你所說,你想按(int,str,int)排序的結果。由於sorted().sort()自動將號碼,在整數的情況下進行排序,並按字母順序,在字符串的情況下,所有你需要爲你鍵功能做的是打破自己的價值,"01AS01"[1, "AS", 1]sorted()/.sort()將照顧其餘。

這是一個和dawg類似的例子,但是沒有使用map()re

col = ['01AA01', 
'01AS01', 
'01NA01', 
'01BA01', 
'01MA01', 
'01AA02', 
'01AS02', 
'02BA01'] 

def create_sort_key(value): 
    int_indexes = (0, 4) 
    str_indexes = (2,) 
    parsed_values = [] 
    # get the starting index for groups of two 
    for i in range(0, 6, 2): 
     pair = value[i:i+2] 
     if i in int_indexes: 
      parsed_value = int(pair) 
     elif i in str_indexes: 
      parsed_value = str(pair) 
     else: 
      raise IndexError("unexpected index: {}".format(i)) 
     parsed_values.append(parsed_value) 
    return parsed_values 

col.sort(key=create_sort_key) 
0

假設這是一個csv文件,每一行是一個行和每列被標記用逗號。既然沒有給我們一個你的csv的例子,我編了一個有兩列的文章,你的數據在col [1]中。

>>> print open('mycsv.csv').read() 
fred, 01AA01 
brenda, 01BA01 
bob, 01AA02 
alice, 01NA01 
jane, 01AS01 
blane, 02BA01 
larry, 01MA01 
mary, 01AS02 

這些都可以通過csv模塊讀入列表中。最後列出行,其中列是另一個列表

>>> import csv 
>>> table=[row for row in csv.reader(open('mycsv.csv')) if row] 
>>> print table 
[['fred', ' 01AA01'], ['brenda', ' 01BA01'], ['bob', ' 01AA02'], ['alice', ' 01NA01'], ['jane', ' 01AS01'], ['blane', ' 02BA01'], ['larry', ' 01MA01'], ['mary', ' 01AS02']] 

您可以對該列表進行排序。默認情況下,排序從第一個鍵開始,然後第二個鍵如果第一個鍵是相同的,等等。所以,它將由'fred'等等來排序......但是您可以選擇不同的排序鍵。 Python調用每個列表項的關鍵函數,以便您可以將其轉換爲您想要的。轉換可以很簡單,如小寫或複雜。

它通常使用lambdas作爲排序鍵,但這可能有點高級,所以這裏有一個函數,它只是抓住你想要的鍵。

>>> def item_1(row): 
...  return row[1] 
... 
>>> print table 
[['fred', ' 01AA01'], ['bob', ' 01AA02'], ['jane', ' 01AS01'], ['mary', ' 01AS02'], ['brenda', ' 01BA01'], ['larry', ' 01MA01'], ['alice', ' 01NA01'], ['blane', ' 02BA01']] 
>>>