如何根据存储在另一个数据框中的子字符串和行数过滤此 pandas 数据框?
How can I filter this pandas dataframe based with substrings and row counts stored in another dataframe?
我有一个数据框,其中一列中包含一组人名作为字符串。
然后我还有一个数据框,其中包含一个人名列表(每个人的名字 1 个数据框行)。所描述的示例数据集:
groupsofpeople = pd.DataFrame({'group':['Genie, Chris, Mike, Dee','Chase, Chris,
William S.','Mike, Tim', 'William S., Chris, Tim'], 'rank':[1,2,3,4]})
people = pd.DataFrame({'name':['Chris','Chase','Ross Rick', 'William S.'],
'rowcnt':[30,25,15,25]})
group rank
0 Genie, Chris, Mike, Dee 1
1 Chase, Chris, William S. 2
2 Mike, Tim 3
3 William S., Chris, Tim 4
>>> people
name rowcnt
0 Chris 2
1 Chase 3
2 Ross Rick 1
3 William S. 2
我的目标是遍历 'people' 数据框名称,如果组中有 1 个名称匹配,则定位 groupsofpeople 中的行。额外的警告是,我还想将每一行过滤为仅 return rowcnt 列中的人数。因此,如果 groupsofpeople 数据框有 5 行包含 Chris,则在应用过滤器之前执行此语句,然后在找到子字符串后,只有前 2 行被 returned(作为特定顺序的 groupsofpeople 区域)。
我没有完全掌握列表理解来自行解决这个问题,但我可以告诉你,如果有一种方法可以遍历名称(在 str.contains() 中)以及 rowcnt(在 head() 中):
founddf = groupsofpeople[groupsofpeople['group'].str.contains('Chris')].head(2)
upload = pd.concat([upload,founddf],ignore_index=False, sort=False)
founddf = groupsofpeople[groupsofpeople['group'].str.contains('Chase')].head(3)
upload = pd.concat([upload,founddf],ignore_index=False, sort=False)
founddf = groupsofpeople[groupsofpeople['group'].str.contains('Ross Rick')].head(1)
upload = pd.concat([upload,founddf],ignore_index=False, sort=False)
这是我希望在不对 loop/iterations 进行硬编码的情况下获得的结果:
group rank
Chase, Chris, William S. 2
Genie, Chris, Mike, Dee 1
Chase, Chris, William S. 2
谁能帮我实现这个解决方案?
这是一种根据 people
数据帧
中的 'rowcnt' 值输出每个人的前 n 行的方法
names = set(people.name)
people2 = people.set_index('name')
(groupsofpeople
.assign(group_list=groupsofpeople['group'].str.split(', ').apply(lambda x: set(x).intersection(names)))
.explode('group_list')
.dropna(subset=['group_list'])
.groupby(['group_list'])
.apply(lambda d: d.head(people2.loc[d.name, 'rowcnt']))
.reset_index(drop=True)
#.drop('group_list', axis=1) #kept here to see groups
)
输出:
group rank group_list
0 Chase, Chris, William S. 2 Chase
1 Genie, Chris, Mike, Dee 1 Chris
2 Chase, Chris, William S. 2 Chris
3 Chase, Chris, William S. 2 William S.
4 William S., Chris, Tim 4 William S.
我有一个数据框,其中一列中包含一组人名作为字符串。 然后我还有一个数据框,其中包含一个人名列表(每个人的名字 1 个数据框行)。所描述的示例数据集:
groupsofpeople = pd.DataFrame({'group':['Genie, Chris, Mike, Dee','Chase, Chris,
William S.','Mike, Tim', 'William S., Chris, Tim'], 'rank':[1,2,3,4]})
people = pd.DataFrame({'name':['Chris','Chase','Ross Rick', 'William S.'],
'rowcnt':[30,25,15,25]})
group rank
0 Genie, Chris, Mike, Dee 1
1 Chase, Chris, William S. 2
2 Mike, Tim 3
3 William S., Chris, Tim 4
>>> people
name rowcnt
0 Chris 2
1 Chase 3
2 Ross Rick 1
3 William S. 2
我的目标是遍历 'people' 数据框名称,如果组中有 1 个名称匹配,则定位 groupsofpeople 中的行。额外的警告是,我还想将每一行过滤为仅 return rowcnt 列中的人数。因此,如果 groupsofpeople 数据框有 5 行包含 Chris,则在应用过滤器之前执行此语句,然后在找到子字符串后,只有前 2 行被 returned(作为特定顺序的 groupsofpeople 区域)。
我没有完全掌握列表理解来自行解决这个问题,但我可以告诉你,如果有一种方法可以遍历名称(在 str.contains() 中)以及 rowcnt(在 head() 中):
founddf = groupsofpeople[groupsofpeople['group'].str.contains('Chris')].head(2)
upload = pd.concat([upload,founddf],ignore_index=False, sort=False)
founddf = groupsofpeople[groupsofpeople['group'].str.contains('Chase')].head(3)
upload = pd.concat([upload,founddf],ignore_index=False, sort=False)
founddf = groupsofpeople[groupsofpeople['group'].str.contains('Ross Rick')].head(1)
upload = pd.concat([upload,founddf],ignore_index=False, sort=False)
这是我希望在不对 loop/iterations 进行硬编码的情况下获得的结果:
group rank
Chase, Chris, William S. 2
Genie, Chris, Mike, Dee 1
Chase, Chris, William S. 2
谁能帮我实现这个解决方案?
这是一种根据 people
数据帧
names = set(people.name)
people2 = people.set_index('name')
(groupsofpeople
.assign(group_list=groupsofpeople['group'].str.split(', ').apply(lambda x: set(x).intersection(names)))
.explode('group_list')
.dropna(subset=['group_list'])
.groupby(['group_list'])
.apply(lambda d: d.head(people2.loc[d.name, 'rowcnt']))
.reset_index(drop=True)
#.drop('group_list', axis=1) #kept here to see groups
)
输出:
group rank group_list
0 Chase, Chris, William S. 2 Chase
1 Genie, Chris, Mike, Dee 1 Chris
2 Chase, Chris, William S. 2 Chris
3 Chase, Chris, William S. 2 William S.
4 William S., Chris, Tim 4 William S.