首页 > 解决方案 > Pandas - 选择其他列行满足两个条件的索引

问题描述

我不确定问题的措辞是否足够准确,我希望代码示例能更好地解释问题。

我有数据框:

                                 links                         title
url                                                                         
https://example.com           /feed.xml                       EXAMPLE
https://example.com           /tags.html                      EXAMPLE
https://example.com           /tags.html                      EXAMPLE
https://example.com           /about                          EXAMPLE
https://example.com           /feed.xml                       EXAMPLE
https://example.com           /feed.xml                       EXAMPLE
https://example222.com        /about/                         EXAMPLE222
https://example222.com        /about/                         EXAMPLE222
https://example333.com        /atom.xml                       EXAMPLE333
https://example333.com        /archives                       EXAMPLE333
https://example333.com        /about                          EXAMPLE333
https://example333.com        /archives                       EXAMPLE333

索引设置为url。但我也可以将其视为具有数字索引的列。

如何仅选择在列中同时包含和字符串的索引 .xml( url) ?archivelinks

IE。

https://example333.com        /atom.xml                       EXAMPLE333
https://example333.com        /archives                       EXAMPLE333

但不是

https://example222.com        /about/                         EXAMPLE222
https://example222.com        /about/                         EXAMPLE222

显然.str.contains('archive|xml'),即使只满足一个条件,也可以简单地选择行。

在此示例中,它还将选择:

https://example.com           /feed.xml                       EXAMPLE
https://example.com           /tags.html                      EXAMPLE

这不是我想要的。

有或没有的解决方案set_index都是好的。

标签: pythonpandas

解决方案


第一个想法是使用Series.str.extractforSeries并将其转换为sets 比较两个值(如果每个组都存在):

s = df['links'].str.extract('(archive|xml)', expand=False)
m = s.groupby(df['url']).apply(set) >= set(['xml','archive'])

然后Series.map屏蔽原始数据并与另一个条件链接

df = df[df['url'].map(m) & s.notna()]
#alternative
#df = df[df['url'].map(m) & df['links'].str.contains('archive|xml')]
print (df)
                       url      links       title
8   https://example333.com  /atom.xml  EXAMPLE333
9   https://example333.com  /archives  EXAMPLE333
11  https://example333.com  /archives  EXAMPLE333

如果想要每个urladd的唯一值DataFrame.drop_duplicates

df = df[df['url'].map(m) & s.notna()].drop_duplicates(['url','links'])
print (df)
                      url      links       title
8  https://example333.com  /atom.xml  EXAMPLE333
9  https://example333.com  /archives  EXAMPLE333

另一种方法应该是计算 2 个辅助列中的匹配值,并测试两个列是否与比较总和值匹配DataFrame.all

a = df['links'].str.contains('archive')
b = df['links'].str.contains('xml')

mask = df.assign(a=a,b=b).groupby('url')['a','b'].transform('sum').gt(0).all(axis=1)

df = df[mask & (a | b)]
print (df)
8   https://example333.com  /atom.xml  EXAMPLE333
9   https://example333.com  /archives  EXAMPLE333
11  https://example333.com  /archives  EXAMPLE333

推荐阅读