在pandas中使用groupby筛选数据

3
我有一个DataFrame,其中包含以下数据。每一行代表一部电视剧中出现的单词。如果一个单词在一集中出现了3次,则pandas dataframe将有3行。现在我需要过滤一个单词列表,只获取出现2次或更多次的单词。我可以通过groupby来实现,但是如果一个单词出现了2(或者说3、4或5)次,我需要它重复两次(3、4或5次)。
通过groupby,我只会得到唯一的条目和计数,但我需要条目重复出现与其在对话中出现的次数相同。是否有一种一行代码就能实现这个功能?
       dialogue  episode
0         music        1
1   corrections        1
2       somnath        1
3         yadav        5
4          join        2
5     instagram        1
6          wind        2
7         music        1
8    whimpering        2
9         music        1
10         wind        3

这里理想情况下应该得到:
   dialogue  episode
0     music        1
6      wind        2
7     music        1
9     music        1
10     wind        3

因为这两个单词出现了2次或更多次,所以这些是唯一的两个单词。
3个回答

5

你可以使用groupby的filter函数:

In [11]: df.groupby("dialogue").filter(lambda x: len(x) > 1)
Out[11]:
   dialogue  episode
0     music        1
6      wind        2
7     music        1
9     music        1
10     wind        3

我更喜欢这个解决方案 - MaxU - stand with Ukraine

4

更新问题的答案:

In [208]: df.groupby('dialogue')['episode'].transform('size') >= 3
Out[208]:
0      True
1     False
2     False
3     False
4     False
5     False
6     False
7      True
8     False
9      True
10    False
dtype: bool

In [209]: df[df.groupby('dialogue')['episode'].transform('size') >= 3]
Out[209]:
  dialogue  episode
0    music        1
7    music        1
9    music        1

原问题的答案:

你可以使用duplicated()方法:

In [202]: df[df.duplicated(subset=['dialogue'], keep=False)]
Out[202]:
   dialogue  episode
0     music        1
6      wind        2
7     music        1
9     music        1
10     wind        3

如果您想对结果进行排序:

In [203]: df[df.duplicated(subset=['dialogue'], keep=False)].sort_values('dialogue')
Out[203]:
   dialogue  episode
0     music        1
7     music        1
9     music        1
6      wind        2
10     wind        3

我有一个更广泛的问题在我的脑海中,如果我需要按一个单词出现超过5(或7、8或9)次的标准进行过滤,那么应该做出什么改变。 - Amrith Krishna

1

I'd use value_counts

vc = df.dialogue.value_counts() >= 2
vc = vc[vc]
df[df.dialogue.isin(vc.index)]

enter image description here


计时

请记住,这完全是过头了。然而,我正在提高我的计时技能。

代码

from timeit import timeit

def pirsquared(df):
    vc = df.dialogue.value_counts() > 1
    vc = vc[vc]
    return df[df.dialogue.isin(vc.index)]

def maxu(df):
    return df[df.groupby('dialogue')['episode'].transform('size') > 1]

def andyhayden(df):
    return df.groupby("dialogue").filter(lambda x: len(x) > 1)

rows = ['pirsquared', 'maxu', 'andyhayden']
cols = ['OP_Given', '10000_3_letters']

summary = pd.DataFrame([], rows, cols)
iterations = 10

df = pd.DataFrame({'dialogue': {0: 'music', 1: 'corrections', 2: 'somnath', 3: 'yadav', 4: 'join', 5: 'instagram', 6: 'wind', 7: 'music', 8: 'whimpering', 9: 'music', 10: 'wind'}, 'episode': {0: 1, 1: 1, 2: 1, 3: 5, 4: 2, 5: 1, 6: 2, 7: 1, 8: 2, 9: 1, 10: 3}})

summary.loc['pirsquared', 'OP_Given'] = timeit(lambda: pirsquared(df), number=iterations)
summary.loc['maxu', 'OP_Given'] = timeit(lambda: maxu(df), number=iterations)
summary.loc['andyhayden', 'OP_Given'] = timeit(lambda: andyhayden(df), number=iterations)


df = pd.DataFrame(
    pd.DataFrame(np.random.choice(list(lowercase), (10000, 3))).sum(1),
    columns=['dialogue'])
df['episode'] = 1

summary.loc['pirsquared', '10000_3_letters'] = timeit(lambda: pirsquared(df), number=iterations)
summary.loc['maxu', '10000_3_letters'] = timeit(lambda: maxu(df), number=iterations)
summary.loc['andyhayden', '10000_3_letters'] = timeit(lambda: andyhayden(df), number=iterations)


summary

enter image description here


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