2014-09-22 94 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']] 
>>>