我需要制作一个pandas DataFrame,其中一列填充了带连字符的数字。我能想到的唯一方法就是使用字符串。这一切都很好,直到我需要对它们进行排序以使它们在重新组合后恢复正常。问题是字符串排序如下:
['100-200','1000-1100','1100-1200','200-300']
这显然不是我想要它排序的方式。我希望它按数字排序。我怎么能让这个工作?我愿意改变一切。将带连字符的字符串保持为整数或浮点数将是最好的,但我不确定如何做到这一点。
答案 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