【问题标题】:Pandas: Counting unique values in a dataframePandas:计算数据框中的唯一值
【发布时间】:2014-12-02 23:23:27
【问题描述】:

我们有一个如下所示的 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,因为nans 已被删除。

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

虽然看起来很笨重。如果有更好的选择,我很高兴听到。

编辑:Dan 的评论显示我有一个错字,尽管更正仍然没有让我们到达终点线。

【问题讨论】:

  • df.stack().groupby(list('aaaabbbb')).value_counts() 为我工作。
  • @DanAllan 嗯,value_counts 快捷方式已在 0.13+ 中关闭(以为它已列入白名单,但猜不...)

标签: python pandas


【解决方案1】:

我认为您正在执行按行/列操作,因此可以使用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

注意:有一个 value_counts DataFrame 方法正在为 0.14 工作......这将使其更高效、更简洁。

值得注意的是,pandas value_counts 函数也适用于 numpy 数组,因此您可以将 DataFrame 的值传递给它(使用np.ravel 作为一维数组视图) :

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])

【讨论】:

  • 谢谢,安迪。这接近了,但分组仍然不太正确。请参阅我即将放入原始问题的示例。另外,堆栈是否返回副本而不是视图?
  • 问题是 nans 使行数可变,因此我们无法提前知道如何为d.stack() 构造合适的分组器。正如你所做的那样,最好在没有stack 的情况下进行操作;我只是看不到在其中获得适当分组的方法。
  • @jeffalstott 你按级别分组,堆栈是副本。我很困惑你真正想要的最终结果是什么......
  • 找到了解决方案。很高兴听到更好的方法。在此期间,我会接受你的回答。
【解决方案2】:

没有足够的代表发表评论,但安迪的回答:

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?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 2018-07-26
    相关资源
    最近更新 更多