python - 计算两列中任一列中字符串出现次数的矢量化方法

标签 python string pandas numpy dataframe

我有一个类似于 this question 的问题, 但只是不同到不能用相同的解决方案来解决...

我有两个数据帧,df1df2,如下所示:

import pandas as pd
import numpy as np
np.random.seed(42)
names = ['jack', 'jill', 'jane', 'joe', 'ben', 'beatrice']
df1 = pd.DataFrame({'ID_a':np.random.choice(names, 20), 'ID_b':np.random.choice(names,20)})    
df2 = pd.DataFrame({'ID':names})

>>> df1
        ID_a      ID_b
0        joe       ben
1        ben      jack
2       jane       joe
3        ben      jill
4        ben  beatrice
5       jill       ben
6       jane       joe
7       jane      jack
8       jane      jack
9        ben      jane
10       joe      jane
11      jane      jill
12  beatrice       joe
13       ben       joe
14      jill  beatrice
15       joe  beatrice
16  beatrice  beatrice
17  beatrice      jane
18      jill       joe
19       joe       joe

>>> df2
         ID
0      jack
1      jill
2      jane
3       joe
4       ben
5  beatrice

我想做的是在 df2 中添加一列,count 行在 df1 中,其中给定的名称可以在 ID_aID_b 中找到,结果是:

>>> df2
         ID  count
0      jack      3
1      jill      5
2      jane      8
3       joe      9
4       ben      7
5  beatrice      6

这个循环得到了我需要的东西,但是对于大型数据帧来说效率低下,如果有人可以建议一个更好的替代解决方案,我将非常感激:

df2['count'] = 0

for idx,row in df2.iterrows():
    df2.loc[idx, 'count'] = len(df1[(df1.ID_a == row.ID) | (df1.ID_b == row.ID)])

提前致谢!

最佳答案

“任一”部分使事情复杂化,但仍然可行。


选项 1
由于其他用户决定将其变成一场速度竞赛,所以这是我的:

from collections import Counter
from itertools import chain

c = Counter(chain.from_iterable(set(x) for x in df1.values.tolist()))
df2['count'] = df2['ID'].map(Counter(c))
df2

         ID  count
0      jack      3
1      jill      5
2      jane      8
3       joe      9
4       ben      7
5  beatrice      6

176 µs ± 7.69 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

选项 2
(原始答案)基于堆栈

c = df1.stack().groupby(level=0).value_counts().count(level=1)

或者,

c = df1.stack().reset_index(level=0).drop_duplicates()[0].value_counts()

或者,

v = df1.stack()
c = v.groupby([v.index.get_level_values(0), v]).count().count(level=1)
# c = v.groupby([v.index.get_level_values(0), v]).nunique().count(level=1)

还有,

df2['count'] = df2.ID.map(c)
df2

         ID  count
0      jack      3
1      jill      5
2      jane      8
3       joe      9
4       ben      7
5  beatrice      6

选项 3
基于repeat的 reshape 和计数

v = pd.DataFrame({
        'i' : df1.values.reshape(-1, ), 
        'j' : df1.index.repeat(2)
    })
c = v.loc[~v.duplicated(), 'i'].value_counts()

df2['count'] = df2.ID.map(c)
df2

         ID  count
0      jack      3
1      jill      5
2      jane      8
3       joe      9
4       ben      7
5  beatrice      6

选项 4
concat + 掩码

v = pd.concat(
    [df1.ID_a, df1.ID_b.mask(df1.ID_a == df1.ID_b)], axis=0
).value_counts()

df2['count'] = df2.ID.map(v)
df2

         ID  count
0      jack      3
1      jill      5
2      jane      8
3       joe      9
4       ben      7
5  beatrice      6

关于python - 计算两列中任一列中字符串出现次数的矢量化方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49413515/

相关文章:

python - 何时使用 pandas 系列、numpy ndarrays 或简单的 python 字典?

Python pip 安装报错

python - 使用 Dataset api tensorflow 即时生成

javascript - 带有 jQ​​uery ajax 的字符串中的单引号

python - 如何向 pandas 数据框的特定列添加值?

python - 如何从 matplotlib ginput 中切片列表

java - 如何使unicode从java中的方法返回类型打印

java - 将每个单词的第一个字母移动到末尾并添加一个字符,有条件

python - 编辑两个 Pandas 列之间的距离

python - 确定 Pandas df 列是否为数组