在 Pandas 中按值计数重新分配字符串

Bry*_*yan 3 python pandas scikit-learn

我在pandas数据框中有许多基于字符串的列,我希望在scikitlearn分类模型上使用它们。我知道我必须使用oneHotEncoder正确编码变量,但首先,我想减少列中的变化,取出列中出现时间少于 x% 或不在前 x 中的字符串字符串按列中的计数。

下面是一个例子:

df1 = pd.DataFrame({'a':range(22), 'b':list('aaaaaaaabbbbbbbcccdefg'), 'c':range(22)})
df1
     a  b   c
0    0  a   0
1    1  a   1
2    2  a   2
3    3  a   3
4    4  a   4
5    5  a   5
6    6  a   6
7    7  a   7
8    8  b   8
9    9  b   9
10  10  b  10
11  11  b  11
12  12  b  12
13  13  b  13
14  14  b  14
15  15  c  15
16  16  c  16
17  17  c  17
18  18  d  18
19  19  e  19
20  20  f  20
21  21  g  21
Run Code Online (Sandbox Code Playgroud)

如您所见,a、b 和 c 出现在 b 列中的概率超过 10%,因此我想保留它们。另一方面,d、e、f 和 g 出现不到 10%(实际上大约 5% 的时间),所以我想通过将它们更改为“其他”来分类:

df1['b']
0     a
1     a
2     a
3     a
4     a
5     a
6     a
7     a
8     b
9     b
10    b
11    b
12    b
13    b
14    b
15    c
16    c
17    c
18    other
19    other
20    other
21    other
Run Code Online (Sandbox Code Playgroud)

我同样希望能够说我只想保留出现在前 2 个频率方面的值,以便 b 列看起来像这样:

df1['b']
0     a
1     a
2     a
3     a
4     a
5     a
6     a
7     a
8     b
9     b
10    b
11    b
12    b
13    b
14    b
15    other
16    other
17    other
18    other
19    other
20    other
21    other
Run Code Online (Sandbox Code Playgroud)

我在 Pandas 中没有看到明显的方法来做到这一点,尽管我承认我在 R 中对此了解得更多。有什么想法吗?关于如何使这种对 Nones 健壮的任何想法,它可能出现超过 10% 的时间或位于 x 值的顶部?

Noa*_*oah 6

这有点扭曲,但这是一个复杂的问题。

首先,获取计数:

In [24]: sizes = df1["b"].value_counts()

In [25]: sizes
Out[25]: 
b
a    8
b    7
c    3
d    1
e    1
f    1
g    1
dtype: int64
Run Code Online (Sandbox Code Playgroud)

现在,选择您不喜欢的索引:

In [27]: bad = sizes.index[sizes < df1.shape[0]*0.1]

In [28]: bad
Out[28]: Index([u'd', u'e', u'f', u'g'], dtype='object')
Run Code Online (Sandbox Code Playgroud)

最后,将“other”分配给那些包含错误索引的行:

In [34]: df1.loc[df1["b"].isin(bad), "b"] = "other"

In [36]: df1
Out[36]: 
     a      b   c
0    0      a   0
1    1      a   1
2    2      a   2
3    3      a   3
4    4      a   4
5    5      a   5
6    6      a   6
7    7      a   7
8    8      b   8
9    9      b   9
10  10      b  10
11  11      b  11
12  12      b  12
13  13      b  13
14  14      b  14
15  15      c  15
16  16      c  16
17  17      c  17
18  18  other  18
19  19  other  19
20  20  other  20
21  21  other  21

[22 rows x 3 columns]
Run Code Online (Sandbox Code Playgroud)

您可以使用sizes.sort()n从结果中获取最后一个值,以便仅找到前两个索引。

编辑:你应该能够做这样的事情,用以下内容替换“b”的所有实例filterByColumn

def filterDataFrame(df1, filterByColumn):
    sizes = df1[filterByColumn].value_counts()
    ...
Run Code Online (Sandbox Code Playgroud)