带连字符的数字或带连字符的数字串

时间:2013-12-31 20:40:51

标签: python sorting hyphen

我需要制作一个pandas DataFrame,其中一列填充了带连字符的数字。我能想到的唯一方法就是使用字符串。这一切都很好,直到我需要对它们进行排序以使它们在重新组合后恢复正常。问题是字符串排序如下:

['100-200','1000-1100','1100-1200','200-300']

这显然不是我想要它排序的方式。我希望它按数字排序。我怎么能让这个工作?我愿意改变一切。将带连字符的字符串保持为整数或浮点数将是最好的,但我不确定如何做到这一点。

2 个答案:

答案 0 :(得分:3)

您可以尝试这样的事情:

>>> t = ['100-200','1000-1100','1100-1200','200-300']
>>> t.sort(key=lambda x: [int(y) for y in x.split('-')])
>>> t
['100-200', '200-300', '1000-1100', '1100-1200']

这将允许您对整数进行排序,如果存在连字符,它将首先按键列表中的第一个整数排序,然后按第二个整数排序。如果不存在连字符,则只对字符串的等效整数进行排序:

>>> t = ['100-200','1000-1100','1100-1200','200-300', '100']
>>> t.sort(key=lambda x: [int(y) for y in x.split('-')])
>>> t
['100', '100-200', '200-300', '1000-1100', '1100-1200']

如果您在任何字符串中都有float个等效项,只需将int更改为float,如下所示:

>>> t = ['100-200.3','1000.5-1100','1100.76-1200','200-300.75', '100.35']
>>> t.sort(key=lambda x: [float(y) for y in x.split('-')])
>>> t
['100-200.3', '100.35', '200-300.75', '1000.5-1100', '1100.76-1200']

答案 1 :(得分:2)

您可以使用sorted为索引构建新的排序,然后使用df.take执行排序(重新排序):

import pandas as pd

df = pd.DataFrame({'foo':['100-200','1000-1100','1100-1200','200-300']})
order = sorted(range(len(df)),
               key=lambda idx: map(int, df.ix[idx, 'foo'].split('-')))
df = df.take(order)
print(df)

产量

         foo
0    100-200
3    200-300
1  1000-1100
2  1100-1200

这类似于@ 275365的解决方案,但请注意,排序是在range(len(df))上完成的,而不是在字符串上。字符串仅用于key参数,以确定range(len(df))应重新排列的顺序。


如果DataFrame较小,则使用sorted可以正常工作。当DataFrame中等大小(例如,我的计算机上有几百行)时,您可以通过使用numpy.argsort来获得更好的效果:

import pandas as pd
import numpy as np

df = pd.DataFrame({'foo':['100-200','1000-1100','1100-1200','200-300']*100})

arr = df['foo'].map(lambda item: map(int, item.split('-'))).values
order = np.argsort(arr)
df = df.take(order)

或者,您可以将字符串列拆分为两个整数值列,然后使用df.sort

import pandas as pd

df = pd.DataFrame({'foo':['100-200','1000-1100','1100-1200','200-300']})

df[['start', 'end']] = df['foo'].apply(lambda val: pd.Series(map(int, val.split('-'))))
df.sort(['start', 'end'], inplace=True)
print(df)

产量

         foo  start   end
0    100-200    100   200
3    200-300    200   300
1  1000-1100   1000  1100
2  1100-1200   1100  1200