如果列中的值在一组值列表中,则过滤数据框行[重复]
Posted
技术标签:
【中文标题】如果列中的值在一组值列表中,则过滤数据框行[重复]【英文标题】:Filter dataframe rows if value in column is in a set list of values [duplicate] 【发布时间】:2012-08-17 10:47:01 【问题描述】:我有一个 Python pandas DataFrame rpt
:
rpt
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 47518 entries, ('000002', '20120331') to ('603366', '20091231')
Data columns:
STK_ID 47518 non-null values
STK_Name 47518 non-null values
RPT_Date 47518 non-null values
sales 47518 non-null values
我可以像这样过滤股票 id 为'600809'
的行:rpt[rpt['STK_ID'] == '600809']
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 25 entries, ('600809', '20120331') to ('600809', '20060331')
Data columns:
STK_ID 25 non-null values
STK_Name 25 non-null values
RPT_Date 25 non-null values
sales 25 non-null values
我想把一些股票的所有行放在一起,例如['600809','600141','600329']
。这意味着我想要这样的语法:
stk_list = ['600809','600141','600329']
rst = rpt[rpt['STK_ID'] in stk_list] # this does not works in pandas
既然pandas不接受上面的命令,那么如何实现目标呢?
【问题讨论】:
stk_list = ['600809','600141','600329'] result=filter(lambda item: item in stk_list,df['STK_ID']) 您可以使用 filter 来获取列表可迭代的项目。 【参考方案1】:使用isin
方法:
rpt[rpt['STK_ID'].isin(stk_list)]
【讨论】:
对此的否定呢? 处理!isin()
的正确方法是什么?
@dbyte:您只需使用~
运算符:rpt[~rpt['STK_ID'].isin(stk_list)]
与@mathtick 所问的有关:有没有办法在一般索引上执行此操作(不一定是多索引)?
@user1669710:索引也有一个isin
方法。
如果有人需要索引的语法:df[df.index.isin(ls)]
ls 是你的列表【参考方案2】:
如果您有一个完全匹配的列表,isin()
是理想的选择,但是如果您有一个部分匹配或子字符串的列表要查找,您可以使用str.contains
方法和正则表达式进行过滤。
例如,如果我们要返回一个 DataFrame,其中所有股票 ID 以 '600'
开头,然后是任意三个数字:
>>> rpt[rpt['STK_ID'].str.contains(r'^600[0-9]3$')] # ^ means start of string
... STK_ID ... # [0-9]3 means any three digits
... '600809' ... # $ means end of string
... '600141' ...
... '600329' ...
... ... ...
假设现在我们有一个字符串列表,我们希望'STK_ID'
中的值以这些字符串结尾,例如
endstrings = ['01$', '02$', '05$']
我们可以将这些字符串与正则表达式“或”字符|
连接起来,并将字符串传递给str.contains
以过滤DataFrame:
>>> rpt[rpt['STK_ID'].str.contains('|'.join(endstrings)]
... STK_ID ...
... '155905' ...
... '633101' ...
... '210302' ...
... ... ...
最后,contains
可以忽略大小写(通过设置case=False
),让您在指定要匹配的字符串时更加通用。
例如,
str.contains('pandas', case=False)
将匹配 PANDAS
、PanDAs
、paNdAs123
等等。
【讨论】:
感谢您。正则表达式搜索会很有帮助。即使isin
仅适用于完美匹配,它也接受dataframes
、Series
、Index
等。@jakevdp 在这里提供了一个很好的解决方案,它可以提取df1
的匹配值,给定另一个数据框df2
:***.com/a/33282617/4752883。就我而言,我有一个df2
,但df2
中的值不会完全匹配,所以我想知道是否有办法在isin
(或其他函数)中使用regex
,类似于你在这里指出了吗?【参考方案3】:
您还可以通过以下方式使用范围:
b = df[(df['a'] > 1) & (df['a'] < 5)]
【讨论】:
【参考方案4】:您也可以直接query您的DataFrame 获取此信息。
rpt.query('STK_ID in (600809,600141,600329)')
或者类似地搜索范围:
rpt.query('60000 < STK_ID < 70000')
【讨论】:
或通过名为my_list
rpt.query('STK_ID in @my_list')
的列表查询【参考方案5】:
使用 pandas 切片数据
给定这样的数据框:
RPT_Date STK_ID STK_Name sales
0 1980-01-01 0 Arthur 0
1 1980-01-02 1 Beate 4
2 1980-01-03 2 Cecil 2
3 1980-01-04 3 Dana 8
4 1980-01-05 4 Eric 4
5 1980-01-06 5 Fidel 5
6 1980-01-07 6 George 4
7 1980-01-08 7 Hans 7
8 1980-01-09 8 Ingrid 7
9 1980-01-10 9 Jones 4
有多种选择或切片数据的方法。
使用 .isin
最明显的是.isin
功能。您可以创建一个掩码,为您提供一系列True
/False
语句,这些语句可以应用于这样的数据框:
mask = df['STK_ID'].isin([4, 2, 6])
mask
0 False
1 False
2 True
3 False
4 True
5 False
6 True
7 False
8 False
9 False
Name: STK_ID, dtype: bool
df[mask]
RPT_Date STK_ID STK_Name sales
2 1980-01-03 2 Cecil 2
4 1980-01-05 4 Eric 4
6 1980-01-07 6 George 4
屏蔽是问题的临时解决方案,但在速度和内存方面并不总是表现良好。
带索引
通过将索引设置为STK_ID
列,我们可以使用pandas内置的切片对象.loc
df.set_index('STK_ID', inplace=True)
RPT_Date STK_Name sales
STK_ID
0 1980-01-01 Arthur 0
1 1980-01-02 Beate 4
2 1980-01-03 Cecil 2
3 1980-01-04 Dana 8
4 1980-01-05 Eric 4
5 1980-01-06 Fidel 5
6 1980-01-07 George 4
7 1980-01-08 Hans 7
8 1980-01-09 Ingrid 7
9 1980-01-10 Jones 4
df.loc[[4, 2, 6]]
RPT_Date STK_Name sales
STK_ID
4 1980-01-05 Eric 4
2 1980-01-03 Cecil 2
6 1980-01-07 George 4
这是执行此操作的快速方法,即使索引可能需要一些时间,但如果您想执行多个这样的查询,它可以节省时间。
合并数据帧
这也可以通过合并数据框来完成。这更适合您拥有比这些示例中更多的数据的场景。
stkid_df = pd.DataFrame("STK_ID": [4,2,6])
df.merge(stkid_df, on='STK_ID')
STK_ID RPT_Date STK_Name sales
0 2 1980-01-03 Cecil 2
1 4 1980-01-05 Eric 4
2 6 1980-01-07 George 4
注意
即使有多行具有相同的'STK_ID'
,上述所有方法都有效
【讨论】:
如果您需要检查数据框的两列怎么办?假设我们要检查列表的值是在“STK_ID”还是“sales”中?【参考方案6】:你也可以通过使用'query'和@来获得类似的结果:
例如:
df = pd.DataFrame('A': [1, 2, 3], 'B': ['a', 'b', 'f'])
df = pd.DataFrame('A' : [5,6,3,4], 'B' : [1,2,3, 5])
list_of_values = [3,6]
result= df.query("A in @list_of_values")
result
A B
1 6 2
2 3 3
【讨论】:
这个语法很优雅,这个答案值得更多的支持【参考方案7】:你可以使用query
,即:
b = df.query('a > 1 & a < 5')
【讨论】:
以上是关于如果列中的值在一组值列表中,则过滤数据框行[重复]的主要内容,如果未能解决你的问题,请参考以下文章