使用Python 3.3和Pandas 0.10
我有一个通过连接多个CSV文件构建的DataFrame。首先,我过滤掉Name列中包含特定字符串的所有值。结果看起来像这样(缩短为简洁sakes,实际上有更多列):
Name ID
'A' 1
'B' 2
'C' 3
'C' 3
'E' 4
'F' 4
... ...
现在我的问题是我要删除一个特殊的'重复'值。我想删除所有ID重复项(实际上是整行),其中映射到此ID的相应名称值不类似。在上面的示例中,我想保留ID为1,2和3的行。其中ID = 4,Name值不相等,我想删除它们。
我尝试使用以下代码行(基于此处的建议:Python Pandas: remove entries based on the number of occurrences)。
代码:
df[df.groupby('ID').apply(lambda g: len({x for x in g['Name']})) == 1]
然而,这给了我错误:
ValueError: Item wrong length 51906 instead of 109565!
编辑:
我没有使用apply()
,而是尝试使用transform()
,但这给了我错误:AttributeError: 'int' object has no attribute 'ndim'
。关于为什么每个函数的错误不同的解释非常感谢!
另外,我想在上面的示例中保留ID = 3的所有行。
提前致谢, Matthijs
答案 0 :(得分:5)
而不是长度len
,我认为您要考虑每个组中Name的唯一值的数量。使用nunique()
,并查看这个整齐的配方以过滤组。
df[df.groupby('ID').Name.transform(lambda x: x.nunique() == 1).astype('bool')]
如果你升级到pandas 0.12,你可以在组上使用新的filter
方法,这使得它更加简洁明了。
df.groupby('ID').filter(lambda x: x.Name.nunique() == 1)
一般性评论:有时,当然,你确实想知道小组的长度,但我发现size
比len
更安全,这对我来说很麻烦。有些情况。
答案 1 :(得分:0)
您可以先删除重复项:
In [11]: df = df.drop_duplicates()
In [12]: df
Out[12]:
Name ID
0 A 1
1 B 2
2 C 3
4 E 4
5 F 4
groupby
id并且只考虑具有一个元素的那些:
In [13]: g = df.groupby('ID')
In [14]: size = (g.size() == 1)
In [15]: size
Out[15]:
ID
1 True
2 True
3 True
4 False
dtype: bool
In [16]: size[size].index
Out[16]: Int64Index([1, 2, 3], dtype=int64)
In [17]: df['ID'].isin(size[size].index)
Out[17]:
0 True
1 True
2 True
4 False
5 False
Name: ID, dtype: bool
这是布尔索引:
In [18]: df[df['ID'].isin(size[size].index)]
Out[18]:
Name ID
0 A 1
1 B 2
2 C 3