假设我有一个包含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
我想知道各行A
,B
,C
列的最常见的排序是什么。
在上面的案例中,可以手动对每一行进行排序:
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中是否有任何促进此分析的功能?例如,如果我想找出每次排序的频率怎么办?
答案 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