对包含字符串

时间:2015-07-06 19:47:59

标签: python arrays sorting numpy scipy

问题

我试图计算字符串列表的频率并按降序排序。 scipy.stats.itemfreq生成频率结果,该结果作为字符串元素的numpy数组输出。这是我难倒的地方。我该如何排序?

到目前为止,我已经尝试了operator.itemgetter,它似乎适用于一个小列表,直到我意识到它是按第一个字符串字符排序而不是将字符串转换为整数'5' > '11',因为它是比较51而不是511

我使用的是python 2.7,numpy 1.8.1,scipy 0.14.0。

示例代码:

from scipy.stats import itemfreq
import operator as op

items = ['platypus duck','platypus duck','platypus duck','platypus duck','cat','dog','platypus duck','elephant','cat','cat','dog','bird','','','cat','dog','bird','cat','cat','cat','cat','cat','cat','cat']
items = itemfreq(items)
items = sorted(items, key=op.itemgetter(1), reverse=True)
print items
print items[0]

输出:

[array(['platypus duck', '5'], 
      dtype='|S13'), array(['dog', '3'], 
      dtype='|S13'), array(['', '2'], 
      dtype='|S13'), array(['bird', '2'], 
      dtype='|S13'), array(['cat', '11'], 
      dtype='|S13'), array(['elephant', '1'], 
      dtype='|S13')]
['platypus duck' '5']

预期输出:

订购后我就这样:

[array(['cat', '11'], 
      dtype='|S13'), array(['platypus duck', '5'], 
      dtype='|S13'), array(['dog', '3'], 
      dtype='|S13'), array(['', '2'], 
      dtype='|S13'), array(['bird', '2'], 
      dtype='|S13'), array(['elephant', '1'], 
      dtype='|S13')]
['cat', '11']

摘要

我的问题是:如何按计数的降序对数组(在本例中为字符串数组)进行排序?请随意为我上面的代码示例建议替代和更快/改进的方法。

2 个答案:

答案 0 :(得分:2)

很遗憾,itemfreq在同一个数组中返回唯一项的计数。对于你的情况,这意味着计数被转换为字符串,这只是愚蠢。

如果你可以将numpy升级到版本1.9,那么你可以使用itemfreq而不是numpy.unique,而不是使用return_counts=True(参见下面有关如何在较旧的numpy中完成此操作) :

In [29]: items = ['platypus duck','platypus duck','platypus duck','platypus duck','cat','dog','platypus duck','elephant','cat','cat','dog','bird','','','cat','dog','bird','cat','cat','cat','cat','cat','cat','cat']

In [30]: values, counts = np.unique(items, return_counts=True)

In [31]: values
Out[31]: 
array(['', 'bird', 'cat', 'dog', 'elephant', 'platypus duck'], 
      dtype='|S13')

In [32]: counts
Out[32]: array([ 2,  2, 11,  3,  1,  5])

获取使counts按降序排列的索引:

In [38]: idx = np.argsort(counts)[::-1]

In [39]: values[idx]
Out[39]: 
array(['cat', 'platypus duck', 'dog', 'bird', '', 'elephant'], 
      dtype='|S13')

In [40]: counts[idx]
Out[40]: array([11,  5,  3,  2,  2,  1])

对于旧版numpy,您可以合并np.uniquenp.bincount,如下所示:

In [46]: values, inv = np.unique(items, return_inverse=True)

In [47]: counts = np.bincount(inv)

In [48]: values
Out[48]: 
array(['', 'bird', 'cat', 'dog', 'elephant', 'platypus duck'], 
      dtype='|S13')

In [49]: counts
Out[49]: array([ 2,  2, 11,  3,  1,  5])

In [50]: idx = np.argsort(counts)[::-1]

In [51]: values[idx]
Out[51]: 
array(['cat', 'platypus duck', 'dog', 'bird', '', 'elephant'], 
      dtype='|S13')

In [52]: counts[idx]
Out[52]: array([11,  5,  3,  2,  2,  1])

事实上,上述内容正是itemfreq所做的。这里是scipy源代码中itemfreq的定义(没有docstring):

def itemfreq(a):
    items, inv = np.unique(a, return_inverse=True)
    freq = np.bincount(inv)
    return np.array([items, freq]).T

答案 1 :(得分:0)

完成任务的一种更简单的方法-获取项目的频率并按频率对项目进行排序-使用熊猫函数value_counts(有关原始帖子和更多建议,请参见{{3} }):

import pandas as pd
import numpy as np
x = np.array(["bird","cat","dog","dog","cat","cat"])
pd.value_counts(x)

cat     3
dog     2
bird    1
dtype: int64

仅获取发生的次数,按排序:

y = pd.value_counts(x).values

array([3, 2, 1])

仅获取要计数的项目的唯一名称,排序方式:

z = pd.value_counts(x).index

Index(['cat', 'dog', 'bird'], dtype='object')