【问题标题】:Get columns with distinct value counts greater than a specified value获取不同值计数大于指定值的列
【发布时间】:2018-12-28 12:32:32
【问题描述】:

想象一下以下 Python Pandas 数据框:

df = pd.DataFrame({'id' : ['foo', 'bar', 'foo'], \
                   'A' : ['property1', 'property1', 'property2'], \
                   'B' : ['test', 'test', 'test'] })
from tabulate import tabulate
print(tabulate(df, headers='keys', tablefmt='psql'))

+----+-----------+------+------+
|    | A         | B    | id   |
|----+-----------+------+------|
|  0 | property1 | test | foo  |
|  1 | property1 | test | bar  |
|  2 | property2 | test | foo  |
+----+-----------+------+------+

在这里您可以看到对于 id "foo" 列 B 只有一个唯一(不同)值,即 test。但是对于 A 列,它有两个不同的值 property1property2。对于 id "bar",两列只有一个不同的值。

我正在寻找的是代码,如果按 id 分组,则该代码会给我那些计数大于 1 的列的名称。所以结果应该是 A 列的名称,因为它包含不明确的值。

df.groupby(['id'])

我只知道如何获取计数(出现)大于 1 的 ID。但这不是我最终要寻找的。​​p>

df['id'].value_counts().reset_index(name="count").query("count > 1")["id"]

感谢任何提示。

【问题讨论】:

  • 你能发布你想要的数据集吗?
  • 不,因为它是机密的。因此,我添加了那个小演示数据。
  • 我的意思是您想要的数据集基于您的样本输入数据集...

标签: python pandas group-by pandas-groupby


【解决方案1】:

用途:

#filter column of interest
a = (df.groupby(['id'])['A','B'].nunique() > 1).any()

print (a)
A     True
B    False
dtype: bool

#if need test all columns without id
a = (df.set_index('id').groupby('id').nunique() > 1).any()
print (a)
A     True
B    False
dtype: bool

最后一个过滤器:

b = a.index[a]
print (b)
Index(['A'], dtype='object')

【讨论】:

  • 第二个代码sn-p也是我想的。但我不是在寻找值,而是在寻找包含这些值的列名。这是因为原始数据集大约有 32 列。
  • 不错,效果很好。我使用代码检查所有列但没有设置索引。
  • 对不起,我没有得到 iindexing 部分。它虽然有效。
  • @SourabhMaity - 它通过布尔值过滤a 系列的索引 - 所以在a.index[a] 之后仅获取 True 值的索引。
【解决方案2】:

也许您正在寻找:

g = df.groupby('id')['A', 'B'].nunique()
g

     A  B
id       
bar  1  1
foo  2  1

要获取相关列,只需索引df.columns

df.columns[(g > 1).any()]
Index(['A'], dtype='object')

【讨论】:

  • 这是我的想法:-)
  • 然后您将如何过滤该数据框以获得列名“A”,这是唯一值大于 1 的列。
  • @Matthias df.columns.difference(['id'])[(df.groupby('id')['A', 'B'].nunique() > 1).any()] --> 给A
  • @Bharath df.columns 包含 id 而索引器不包含。
  • 我同意,但我认为既然我们使用的是 groupby,id 将始终具有错误值,因为没有重复。
【解决方案3】:

更新:

In [98]: df.columns.drop('id')[(df.groupby('id')[df.columns.drop('id')].nunique() > 1).any()]
Out[98]: Index(['A'], dtype='object')

In [31]: df[['A','B']].columns[df.groupby(['id'])['A','B'].apply(lambda x: x.nunique().gt(1)).any()]
Out[31]: Index(['A'], dtype='object')

解释:

In [32]: df.groupby(['id'])['A','B'].apply(lambda x: x.nunique().gt(1))
Out[32]:
         A      B
id
bar  False  False
foo   True  False

In [33]: df.groupby(['id'])['A','B'].apply(lambda x: x.nunique().gt(1)).any()
Out[33]:
A     True
B    False
dtype: bool

【讨论】:

  • 找不到方法 .gt 但使用 > 1 代替。无论如何,有没有办法在不使用列名 A 和 B 以及所有列的列表的情况下获取此代码,因为原始数据有很多我需要测试的列。
【解决方案4】:

这是另一种方式

pd.crosstab(df.id,[df.A,df.B],margins =True)
Out[206]: 
A   property1 property2 All
B        test      test    
id                         
bar         1         0   1
foo         1         1   2
All         2         1   3

或者类似的东西

[x if df.groupby(['id',x]).ngroup().max()>1 else np.nan for x in df.columns]
Out[233]: ['A', nan, nan]

【讨论】:

  • 虽然你仍然需要那里的列名。
猜你喜欢
  • 1970-01-01
  • 2018-07-22
  • 1970-01-01
  • 2014-03-20
  • 2013-11-23
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多