列的排序统计

时间:2014-08-22 00:05:00

标签: pandas scipy statsmodels

假设我有一个包含N列的数据框(例如N=3)。每行代表一个样本:

                A        B        C                                
sample_1       64       46       69
sample_2       55       33       40
sample_3       67       51       78
sample_4       97       32       62
sample_5       50       36       39

我想知道各行ABC列的最常见的排序是什么。

在上面的案例中,可以手动对每一行进行排序:

sample_1: [B, A, C]
sample_2: [B, C, A] 
sample_3: [B, A, C]
sample_4: [B, C, A] 
sample_5: [B, C, A]

然后发现最常见的排序是[B, C, A],而[B, A, C]是第二常见的排序。

Pandas,scipy或statsmodels中是否有任何促进此分析的功能?例如,如果我想找出每次排序的频率怎么办?

2 个答案:

答案 0 :(得分:4)

也许:

>>> from collections import Counter
>>> f = lambda ts: df.columns[np.argsort(ts).values]
>>> Counter(map(tuple, df.apply(f, axis=1).values))
Counter({('B', 'C', 'A'): 3, ('B', 'A', 'C'): 2})

所以最常见的排序是:

>>> _.most_common(1)
[(('B', 'C', 'A'), 3)]

可替换地:

>>> f = lambda ts: tuple(df.columns[np.argsort(ts)])
>>> df.apply(f, axis=1, raw=True).value_counts()
(B, C, A)    3
(B, A, C)    2
dtype: int64

答案 1 :(得分:4)

使用cythonized rank函数可能更有效:

In [11]: df.rank(axis=1)
Out[11]:
          A  B  C
sample_1  2  1  3
sample_2  3  1  2
sample_3  2  1  3
sample_4  3  1  2
sample_5  3  1  2

然后你可以做一个groupby,例如获取尺寸:

In [12]: df.rank(axis=1).groupby(['A', 'B', 'C']).size()
Out[12]:
A  B  C
2  1  3    2
3  1  2    3
dtype: int64

注意:这里我们读2 1 3表示[“B”,“A”,“C”],但是你可以根据需要替换结果的索引(即用其中一个替换它)这些):

In [13]: res.index.map(lambda y: ["_ABC"[int(x)] for x in y])
Out[13]: array([['B', 'A', 'C'], ['C', 'A', 'B']], dtype=object)

In [14]: res.index.map(lambda y: "".join(["_ABC"[int(x)] for x in y]))
Out[14]: array(['BAC', 'CAB'], dtype=object)

以下是稍大的数据框的性能:

In [21]: df1 = pd.concat([df] * 1000, ignore_index=True)

In [22]: %timeit df1.rank(axis=1).groupby(['A', 'B', 'C']).size()
100 loops, best of 3: 4.82 ms per loop

In [23]: %timeit Counter(map(tuple, df1.apply(f, axis=1).values))
1 loops, best of 3: 1.68 s per loop