带有列表的pandas数据框中的唯一项

时间:2018-05-18 20:13:34

标签: python pandas dataframe

我尝试从pandas数据框中删除所有列,其中列中的唯一项少于10个。但是,我的一些数据是列表,我收到错误unhashable type: 'list'。有道理,因为pandas与hashmap比较。

我目前的代码是

for i in df.columns:
    if len(df[i].unique()) < 10:
        df.drop(i, 1)

在我到达列表对象之前工作正常。就我的目的而言,list1和list2并不是唯一的。 [1, 2][2, 1]并非唯一,即使[1, 2] == [2, 1]为假。

我该如何进行此操作?将列表分开是没有意义的,因为我有1400个列,所以我无法明确地输入列。

非常感谢提前!

2 个答案:

答案 0 :(得分:2)

list个对象不可清除,因为它们是可变的,但另一方面,tuple是不可变的。您可以transform将值列出到tuple并使用此属性。

假设你有

df = pd.DataFrame({"A": [1,2,3,4], 
                   "B": ["a", "b", "c", "d"],
                   "C": [[1,2,3], [2], [2,3,1], [4]] })

    A   B   C
0   1   a   [1, 2, 3]
1   2   b   [2]
2   3   c   [2, 3, 1]
3   4   d   [4]

因此,您可以执行类似

的操作
df.C.apply(sorted).transform(tuple).unique()

返回

array([(1, 2, 3), (2,), (4,)], dtype=object)

因此,您的代码可能如下所示,使用collections.Hashable来检查列的内容是否确实可以缓存

import collections

for i in df.columns:
    if isinstance(df[i].iloc[0], collections.Hashable):
        if len(df[i].unique()) < 10: 
            df = df.drop(i, 1)
    else:
        if len(df[i].apply(sorted).transform(tuple).unique()) < 10: 
            df = df.drop(i, 1)

请注意,这也适用于其他不可用类型,例如dict s

>>> df["D"] = [{"a":2}, {}, {"k":3}, {"k":3}]})
>>> print(df.D.apply(sorted).transform(tuple).unique())
[('a',) () ('k',)]

答案 1 :(得分:1)

一种方法是将麻烦的类型转换为可清除的替代品。在下面的示例中,有14个元素,但[1, 2] == [2, 1]将双方转换为frozenset,此外还有0 == False。所以我们计算了12个唯一值。

s = pd.Series([[1, 2], [2, 1], (1, 2, 3), {5, 1}, 3142, 563.123, np.nan, 'dfa',
               '', 'dsafa', 3214, 0, True, False])

print(len(s))  # 14

def converter(x):
    return frozenset(x) if isinstance(x, (set, list)) else x

print(len(s.apply(converter).unique()))  # 12