我们有一个如下所示的DataFrame:
> df.ix[:2,:10]
0 1 2 3 4 5 6 7 8 9 10
0 NaN NaN NaN NaN 6 5 NaN NaN 4 NaN 5
1 NaN NaN NaN NaN 8 NaN NaN 7 NaN NaN 5
2 NaN NaN NaN NaN NaN 1 NaN NaN NaN NaN NaN
我们只想要DataFrame中所有唯一值的计数。一个简单的解决方案是:
df.stack().value_counts()
然而:
1.看起来stack
返回副本,而不是视图,在这种情况下,内存禁止。它是否正确?
2.我想按行对DataFrame进行分组,然后为每个分组获取不同的直方图。如果我们忽略stack
的内存问题并暂时使用它,那么如何正确地进行分组呢?
d = pd.DataFrame([[nan, 1, nan, 2, 3],
[nan, 1, 1, 1, 3],
[nan, 1, nan, 2, 3],
[nan,2,2,2, 3]])
len(d.stack()) #14
d.stack().groupby(arange(4))
AssertionError: Grouper and axis must be same length
堆叠的DataFrame有一个MultiIndex,其长度小于n_rows*n_columns
,因为nan
已被移除。
0 1 1
3 2
4 3
1 0 1
1 1
2 1
3 1
4 3
....
这意味着我们不容易知道如何构建我们的分组。仅仅在第一级操作会好得多,但后来我不知道如何应用我真正想要的分组。
d.stack().groupby(level=0).groupby(list('aabb'))
KeyError: 'a'
编辑:一种不使用堆叠的解决方案:
f = lambda x: pd.value_counts(x.values.ravel())
d.groupby(list('aabb')).apply(f)
a 1 4
3 2
2 1
b 2 4
3 2
1 1
dtype: int64
但是,看起来很笨重。如果有更好的选择,我很高兴听到它。
编辑:丹的评论显示我有一个错字,虽然纠正仍然没有让我们到达终点。
答案 0 :(得分:7)
我认为您正在执行行/列操作,因此可以使用apply
:
In [11]: d.apply(pd.Series.value_counts, axis=1).fillna(0)
Out[11]:
1 2 3
0 1 1 1
1 4 0 1
2 1 1 1
3 0 4 1
注意:0.14中有一个value_counts
DataFrame方法,可以提高效率和简洁性。
值得注意的是,pandas value_counts
函数也适用于numpy数组,因此您可以使用{{传递数据框的值作为一维数组视图 3}}):
In [21]: pd.value_counts(d.values.ravel())
Out[21]:
2 6
1 6
3 4
dtype: int64
此外,你非常接近这一点,但你需要堆叠和取消堆栈:
In [22]: d.stack().groupby(level=0).apply(pd.Series.value_counts).unstack().fillna(0)
Out[22]:
1 2 3
0 1 1 1
1 4 0 1
2 1 1 1
3 0 4 1
这个错误似乎有点自我解释(4!= 16):
len(d.stack()) #16
d.stack().groupby(arange(4))
AssertionError: Grouper and axis must be same length
也许你想通过:
In [23]: np.repeat(np.arange(4), 4)
Out[23]: array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3])
答案 1 :(得分:1)
没有足够的代表发表评论,但Andy回答:
pd.value_counts(d.values.ravel())
是我个人使用的,在我看来是迄今为止最通用和易读的解决方案。另一个优点是易于使用列的子集:
pd.value_counts(d[[1,3,4,6,7]].values.ravel())
或
pd.value_counts(d[["col_title1","col_title2"]].values.ravel())
这种方法有什么不利,或者你想使用stack和groupby的任何特殊原因?