Pandas - 统计并获取列中字符串值的唯一出现次数

4

我有一列超过800行的数据如下:

0                            ['Overgrow', 'Chlorophyll']
1                            ['Overgrow', 'Chlorophyll']
2                            ['Overgrow', 'Chlorophyll']
3                               ['Blaze', 'Solar Power']
4                               ['Blaze', 'Solar Power']
5                               ['Blaze', 'Solar Power']
6                               ['Torrent', 'Rain Dish']
7                               ['Torrent', 'Rain Dish']
8                               ['Torrent', 'Rain Dish']
9                            ['Shield Dust', 'Run Away']
10                                         ['Shed Skin']
11                       ['Compoundeyes', 'Tinted Lens']
12                           ['Shield Dust', 'Run Away']
13                                         ['Shed Skin']
14                                   ['Swarm', 'Sniper']
15             ['Keen Eye', 'Tangled Feet', 'Big Pecks']
16             ['Keen Eye', 'Tangled Feet', 'Big Pecks']
17             ['Keen Eye', 'Tangled Feet', 'Big Pecks']

我想要什么?

  1. 我想要计算每个字符串值出现的次数。
  2. 我还想将唯一的字符串值排列成列表。

以下是我为了得到第二部分所做的事情:

list_ability = df_pokemon['abilities'].tolist()
new_list = []
for i in range(0, len(list_ability)):
    m = re.findall(r"'(.*?)'", list_ability[i], re.DOTALL)
    for j in range(0, len(m)):
        new_list.append(m[j])

list1 = set(new_list)  

我能把唯一的字符串值放进一个列表中,但是有没有更好的方法呢?

例子:

'Overgrow' - 3

'Chlorophyll' - 3

'Blaze' - 3

'Sheild Dust' - 2 .... 等等

(顺便说一句,列的名称是'abilities',来自于数据框架df_pokemon。)


你尝试过使用 from collections import Counter; counts = df_pokemon.abilities.map(Counter).sum() 吗? - Jon Clements
@JonClements 它返回每个字母和特殊字符出现的次数。 - Jeru Luke
@JonClements 这个问题的标题是否恰当? - Jeru Luke
2个回答

6

由于这些值是字符串,您可以使用正则表达式和分割将它们转换为列表,然后像@JonClements在评论中提到的那样使用itertools来计数。

from collections import Counter
count  = pd.Series(df['abilities'].str.replace('[\[\]\']','').str.split(',').map(Counter).sum())

输出:

Big Pecks        3
叶绿素          3
雨盘            3
逃跑           2
狙击手          1
太阳能         3
纠缠之爪        3
染色透镜         1
火焰之躯       3
复眼           1
锐利目光         3
茂盛           3
蜕皮           2
飞尘           2
虫之预感        1
激流           3
dtype: int64
dtype: int64

要想生成仅包含唯一值的列表,可以使用 count[count==1].index.tolist()

['Sniper', 'Tinted Lens', 'Compoundeyes', 'Swarm']

为了制作索引列表,则需:
count.index.tolist()

这个运行得非常好。有没有更好的方法来完成我在第二部分问题中所做的事情? - Jeru Luke
不行。但是获得count的索引可以得到唯一的出现次数。无论如何,谢谢!顺便说一句,我希望这个标题适合这个问题。 - Jeru Luke
请注意,如果您的能力名称中包含逗号(或转义字符串分隔符或双引号作为字符串分隔符,因为其中使用了单引号),那么此代码将无法正确拆分它,而与之相反的是ast.literal_eval方法会根据Python列表的规则正确解析它。 - Jon Clements
@JonClements 我同意,但我认为abilities不包含,,因为它不是句子,而是一般的短语或动词。它可能被转换为字符串。 - Bharath M Shetty

3
使用 value_counts 方法。
In [1845]: counts = pd.Series(np.concatenate(df_pokemon.abilities)).value_counts()

In [1846]: counts
Out[1846]:
Rain Dish       3
Keen Eye        3
Chlorophyll     3
Blaze           3
Solar Power     3
Overgrow        3
Big Pecks       3
Tangled Feet    3
Torrent         3
Shield Dust     2
Shed Skin       2
Run Away        2
Compoundeyes    1
Swarm           1
Tinted Lens     1
Sniper          1
dtype: int64

对于唯一的值,您可以

In [1850]: counts.index.tolist()
Out[1850]:
['Rain Dish','Keen Eye', 'Chlorophyll', 'Blaze', 'Solar Power', 'Overgrow', 
 'Big Pecks', 'Tangled Feet', 'Torrent', 'Shield Dust', 'Shed Skin', 'Run Away',
 'Compoundeyes', 'Swarm', 'Tinted Lens', 'Sniper']

或者,

In [1849]: np.unique(np.concatenate(df_pokemon.abilities))
Out[1849]:
array(['Big Pecks', 'Blaze', 'Chlorophyll', 'Compoundeyes', 'Keen Eye',
       'Overgrow', 'Rain Dish', 'Run Away', 'Shed Skin', 'Shield Dust',
       'Sniper', 'Solar Power', 'Swarm', 'Tangled Feet', 'Tinted Lens',
       'Torrent'],
      dtype='|S12')

注意 - 正如Jon的评论所指出的,如果type(df_pokemon.abilities[0])不是list,那么首先要将其转换为列表。

import ast
df_pokemon.abilities = df_pokemon.abilities.map(ast.literal_eval)

细节

In [1842]: df_pokemon
Out[1842]:
                              abilities
0               [Overgrow, Chlorophyll]
1               [Overgrow, Chlorophyll]
2               [Overgrow, Chlorophyll]
3                  [Blaze, Solar Power]
4                  [Blaze, Solar Power]
5                  [Blaze, Solar Power]
6                  [Torrent, Rain Dish]
7                  [Torrent, Rain Dish]
8                  [Torrent, Rain Dish]
9               [Shield Dust, Run Away]
10                          [Shed Skin]
11          [Compoundeyes, Tinted Lens]
12              [Shield Dust, Run Away]
13                          [Shed Skin]
14                      [Swarm, Sniper]
15  [Keen Eye, Tangled Feet, Big Pecks]
16  [Keen Eye, Tangled Feet, Big Pecks]
17  [Keen Eye, Tangled Feet, Big Pecks]

In [1843]: df_pokemon.dtypes
Out[1843]:
abilities    object
dtype: object

In [1844]: type(df_pokemon.abilities[0])
Out[1844]: list

从OP在帖子上发表的评论来看,似乎需要使用df_pokemon.abilities.map(ast.literal_eval)将它们首先转换为列表... - Jon Clements
@Zero 我来解释一下,在abilities这一列中的值是字符串,没有列表。因此,当我键入df_pokemon['abilities'][0]时,它会返回"['Overgrow', 'Chlorophyll']" - Jeru Luke
@JeruLuke -- 执行 df_pokemon.abilities = df_pokemon.abilities.map(ast.literal_eval),然后再按我之前提到的方法使用 value_counts。 - Zero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接