Pandas:计算数据框中的唯一值

jef*_*ott 8 python pandas

我们有一个如下所示的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
Run Code Online (Sandbox Code Playgroud)

我们只想要DataFrame中所有唯一值的计数.一个简单的解决方案是

df.stack().value_counts() 
Run Code Online (Sandbox Code Playgroud)

但是: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
Run Code Online (Sandbox Code Playgroud)

堆叠的DataFrame具有MultiIndex,其长度小于某个数字n_rows*n_columns,因为nans被删除.

0  1    1
   3    2
   4    3
1  0    1
   1    1
   2    1
   3    1
   4    3
    ....
Run Code Online (Sandbox Code Playgroud)

这意味着我们不容易知道如何构建我们的分组.只是在第一级操作会好得多,但后来我不知道如何应用我真正想要的分组.

d.stack().groupby(level=0).groupby(list('aabb'))
KeyError: 'a'
Run Code Online (Sandbox Code Playgroud)

编辑:一种不使用堆叠的解决方案:

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
Run Code Online (Sandbox Code Playgroud)

但是看起来很笨重.如果有更好的选择,我很高兴听到它.

编辑:丹的评论显示我有一个错字,虽然纠正仍然没有让我们到达终点.

And*_*den 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
Run Code Online (Sandbox Code Playgroud)

注意:有一种value_countsDataFrame方法可以用于0.14 ...这将使这更有效,更简洁.

值得注意的是,熊猫value_counts功能还工作的numpy的阵列上,这样就可以把它传递数据帧的值(作为1-d阵列视图使用np.ravel):

In [21]: pd.value_counts(d.values.ravel())
Out[21]: 
2    6
1    6
3    4
dtype: int64
Run Code Online (Sandbox Code Playgroud)

此外,你非常接近正确,但你需要堆叠和取消堆栈:

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
Run Code Online (Sandbox Code Playgroud)

这个错误似乎有点自我解释(4!= 16):

len(d.stack()) #16
d.stack().groupby(arange(4))
AssertionError: Grouper and axis must be same length
Run Code Online (Sandbox Code Playgroud)

也许你想通过:

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])
Run Code Online (Sandbox Code Playgroud)