Python 如何基于列值从数据帧中选择行?
如何根据Pandas中某列中的值从数据框中选择行 在SQL中,我将使用:Python 如何基于列值从数据帧中选择行?,python,pandas,dataframe,Python,Pandas,Dataframe,如何根据Pandas中某列中的值从数据框中选择行 在SQL中,我将使用: 选择* 从桌子上 其中colume\u name=某个值 我试图查看Pandas的文档,但没有立即找到答案。要选择列值等于标量的行,请使用=: df.loc[df['column_name'] == some_value] 要选择列值在iterable中的行,某些值,请使用isin: df.loc[df['column_name'].isin(some_values)] print(df.loc[df['B'].is
选择*
从桌子上
其中colume\u name=某个值
我试图查看Pandas的文档,但没有立即找到答案。要选择列值等于标量的行,请使用
=
:
df.loc[df['column_name'] == some_value]
要选择列值在iterable中的行,
某些值
,请使用isin
:
df.loc[df['column_name'].isin(some_values)]
print(df.loc[df['B'].isin(['one','three'])])
df.loc[df.index.isin(['one','two'])]
将多个条件与和组合:
df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]
被解析为
df['column_name'] >= (A & df['column_name']) <= B
isin
返回一个布尔序列,因此要选择其值不在某些值中的行,请使用~
对布尔序列求反:
df.loc[~df['column_name'].isin(some_values)]
比如说,
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
'B': 'one one two three two two one three'.split(),
'C': np.arange(8), 'D': np.arange(8) * 2})
print(df)
# A B C D
# 0 foo one 0 0
# 1 bar one 1 2
# 2 foo two 2 4
# 3 bar three 3 6
# 4 foo two 4 8
# 5 bar two 5 10
# 6 foo one 6 12
# 7 foo three 7 14
print(df.loc[df['A'] == 'foo'])
屈服
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
A B C D
0 foo one 0 0
1 bar one 1 2
3 bar three 3 6
6 foo one 6 12
7 foo three 7 14
A C D
B
one foo 0 0
one bar 1 2
one foo 6 12
A C D
B
one foo 0 0
one bar 1 2
two foo 2 4
two foo 4 8
two bar 5 10
one foo 6 12
如果要包含多个值,请将它们放在
列出(或更一般地说,任何iterable)并使用isin
:
df.loc[df['column_name'].isin(some_values)]
print(df.loc[df['B'].isin(['one','three'])])
df.loc[df.index.isin(['one','two'])]
屈服
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
A B C D
0 foo one 0 0
1 bar one 1 2
3 bar three 3 6
6 foo one 6 12
7 foo three 7 14
A C D
B
one foo 0 0
one bar 1 2
one foo 6 12
A C D
B
one foo 0 0
one bar 1 2
two foo 2 4
two foo 4 8
two bar 5 10
one foo 6 12
但是,请注意,如果您希望多次执行此操作,则
首先制作索引,然后使用df.loc
:
df = df.set_index(['B'])
print(df.loc['one'])
屈服
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
A B C D
0 foo one 0 0
1 bar one 1 2
3 bar three 3 6
6 foo one 6 12
7 foo three 7 14
A C D
B
one foo 0 0
one bar 1 2
one foo 6 12
A C D
B
one foo 0 0
one bar 1 2
two foo 2 4
two foo 4 8
two bar 5 10
one foo 6 12
或者,要包含索引中的多个值,请使用df.index.isin
:
df.loc[df['column_name'].isin(some_values)]
print(df.loc[df['B'].isin(['one','three'])])
df.loc[df.index.isin(['one','two'])]
屈服
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
A B C D
0 foo one 0 0
1 bar one 1 2
3 bar three 3 6
6 foo one 6 12
7 foo three 7 14
A C D
B
one foo 0 0
one bar 1 2
one foo 6 12
A C D
B
one foo 0 0
one bar 1 2
two foo 2 4
two foo 4 8
two bar 5 10
one foo 6 12
下面是一个简单的例子
from pandas import DataFrame
# Create data set
d = {'Revenue':[100,111,222],
'Cost':[333,444,555]}
df = DataFrame(d)
# mask = Return True when the value in column "Revenue" is equal to 111
mask = df['Revenue'] == 111
print mask
# Result:
# 0 False
# 1 True
# 2 False
# Name: Revenue, dtype: bool
# Select * FROM df WHERE Revenue = 111
df[mask]
# Result:
# Cost Revenue
# 1 444 111
tl;博士
熊猫相当于
select * from table where column_name = some_value
是
多个条件:
table[(table.column_name == some_value) | (table.column_name2 == some_value2)]
或
代码示例
在上面的代码中,df[df.foo==222]
行根据列值给出行,在这种情况下,222
也可能出现多种情况:
df[(df.foo == 222) | (df.bar == 444)]
# bar foo
# 1 444 111
# 2 555 222
但在这一点上,我建议使用该函数,因为它不会太冗长,并且会产生相同的结果:
df.query('foo == 222 | bar == 444')
我发现前面答案的语法是多余的,很难记住。Pandas在v0.13中引入了query()
方法,我更喜欢它。对于您的问题,您可以执行df.query('col==val')
复制自
要附加到这个著名的问题(虽然有点晚了):您还可以执行df.groupby('column\u name')、get\u group('column\u desired\u value')、reset\u index()
来创建一个具有特定值的指定列的新数据帧。例如
import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
'B': 'one one two three two two one three'.split()})
print("Original dataframe:")
print(df)
b_is_two_dataframe = pd.DataFrame(df.groupby('B').get_group('two').reset_index()).drop('index', axis = 1)
#NOTE: the final drop is to remove the extra index column returned by groupby object
print('Sub dataframe where B is two:')
print(b_is_two_dataframe)
运行此命令可提供:
Original dataframe:
A B
0 foo one
1 bar one
2 foo two
3 bar three
4 foo two
5 bar two
6 foo one
7 foo three
Sub dataframe where B is two:
A B
0 foo two
1 foo two
2 bar two
使用以下方法可以获得更快的结果
例如,与-
时间比较:
In [68]: %timeit df.iloc[np.where(df.A.values=='foo')] # fastest
1000 loops, best of 3: 380 µs per loop
In [69]: %timeit df.loc[df['A'] == 'foo']
1000 loops, best of 3: 745 µs per loop
In [71]: %timeit df.loc[df['A'].isin(['foo'])]
1000 loops, best of 3: 562 µs per loop
In [72]: %timeit df[df.A=='foo']
1000 loops, best of 3: 796 µs per loop
In [74]: %timeit df.query('(A=="foo")') # slowest
1000 loops, best of 3: 1.71 ms per loop
有几种方法可以从数据帧中选择行:
布尔索引(df[df['col']==value
])
位置索引(df.iloc[…])
)
标签索引(df.xs(…)
)
df.query(…)
API
下面我将向您展示每种方法的示例,以及何时使用某些技术的建议。假设我们的标准是列'A'
=='foo'
(关于性能的注意:对于每种基本类型,我们可以通过使用Pandas API保持简单,或者我们可以在API之外冒险,通常是进入NumPy,并加快速度。)
设置
我们首先需要确定一个条件,它将作为我们选择行的标准。我们将从OP的casecolumn\u name==some\u value
开始,并包括一些其他常见用例
从@unutbu借款:
import pandas as pd, numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
'B': 'one one two three two two one three'.split(),
'C': np.arange(8), 'D': np.arange(8) * 2})
1。布尔索引
。。。布尔索引需要找到每行'A'
列的真值等于'foo'
,然后使用这些真值来标识要保留的行。通常,我们将这个系列命名为真值数组,mask
。我们在这里也会这样做
mask = df['A'] == 'foo'
然后,我们可以使用此掩码对数据帧进行切片或索引
df[mask]
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
这是完成这项任务最简单的方法之一,如果性能或直觉不是问题,这应该是您选择的方法。但是,如果性能是一个问题,那么您可能需要考虑创建<代码>掩码< /代码>的另一种方式。
2。位置索引
位置索引(df.iloc[…]
)有它的用例,但这不是其中之一。为了确定切片的位置,我们首先需要执行与上面相同的布尔分析。这就让我们多做一步来完成同样的任务
mask = df['A'] == 'foo'
pos = np.flatnonzero(mask)
df.iloc[pos]
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
3。标签索引
标签索引可能非常方便,但在这种情况下,我们再次做了更多的工作,但没有任何好处
df.set_index('A', append=True, drop=False).xs('foo', level=1)
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
4df.query()
API
pd.DataFrame.query
是执行此任务的一种非常优雅/直观的方法,但通常速度较慢但是,如果您注意下面的计时,对于大数据,查询是非常有效的。这比标准方法更重要,与我的最佳建议类似
df.query('A == "foo"')
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
我的首选是使用布尔值
掩码
%timeit mask = df['A'].values == 'foo'
%timeit mask = df['A'] == 'foo'
5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
通过修改如何创建布尔值
掩码
,可以实现实际的改进
mask
备选方案1
使用底层NumPy数组,放弃创建另一个pd.Series
最后,我将展示更多完整的时间测试,但请看一下使用示例数据帧获得的性能提升。首先,我们看一下创建掩码
%timeit mask = df['A'].values == 'foo'
%timeit mask = df['A'] == 'foo'
5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
使用NumPy阵列评估掩码
,速度快约30倍。这部分是由于NumPy评估通常更快。部分原因还在于缺少构建索引和相应的pd.Series
对象所需的开销
接下来,我们将查看使用一个掩码与另一个进行切片的时间
mask = df['A'].values == 'foo'
%timeit df[mask]
mask = df['A'] == 'foo'
%timeit df[mask]
219 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
239 µs ± 7.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
性能的提升并不明显。我们将看看这是否能支持更健壮的测试
mask
备选方案2
我们也可以重建数据帧。重建datafram时有一个很大的警告
res = pd.DataFrame(
index=[
'mask_standard', 'mask_standard_loc', 'mask_with_values', 'mask_with_values_loc',
'query', 'xs_label', 'mask_with_isin', 'mask_with_in1d'
],
columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
dtype=float
)
for j in res.columns:
d = pd.concat([df] * j, ignore_index=True)
for i in res.index:a
stmt = '{}(d)'.format(i)
setp = 'from __main__ import d, {}'.format(i)
res.at[i, j] = timeit(stmt, setp, number=50)
spec.div(spec.min())
10 30 100 300 1000 3000 10000 30000
mask_with_values 1.009030 1.000000 1.194276 1.000000 1.236892 1.095343 1.000000 1.000000
mask_with_in1d 1.104638 1.094524 1.156930 1.072094 1.000000 1.000000 1.040043 1.027100
reconstruct 1.000000 1.142838 1.000000 1.355440 1.650270 2.222181 2.294913 3.406735
spec.T.plot(loglog=True)
np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))
def mask_with_values(df):
mask = df['A'].values == 'foo'
return df[mask]
def mask_with_in1d(df):
mask = np.in1d(df['A'].values, ['foo'])
return df[mask]
def reconstruct(df):
v = df.values
mask = np.in1d(df['A'].values, ['foo'])
return pd.DataFrame(v[mask], df.index[mask], df.columns)
spec = pd.DataFrame(
index=['mask_with_values', 'mask_with_in1d', 'reconstruct'],
columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
dtype=float
)
for j in spec.columns:
d = pd.concat([df] * j, ignore_index=True)
for i in spec.index:
stmt = '{}(d)'.format(i)
setp = 'from __main__ import d, {}'.format(i)
spec.at[i, j] = timeit(stmt, setp, number=50)
select col_name1, col_name2 from table where column_name = some_value.
df.loc[df['column_name'] == some_value][[col_name1, col_name2]]
df.query['column_name' == 'some_value'][[col_name1, col_name2]]
df.apply(lambda row: row[df['B'].isin(['one','three'])])
A B C D
0 foo one 0 0
1 bar one 1 2
3 bar three 3 6
6 foo one 6 12
7 foo three 7 14
df[[df['B'].isin(['one','three'])]]
# Example dataframe
df = pd.DataFrame({'Sender email':['ex@example.com', "reply@shop.com", "buy@shop.com"]})
Sender email
0 ex@example.com
1 reply@shop.com
2 buy@shop.com
df.query('`Sender email`.str.endswith("@shop.com")')
Sender email
1 reply@shop.com
2 buy@shop.com
domain = 'shop.com'
df.query('`Sender email`.str.endswith(@domain)')
Sender email
1 reply@shop.com
2 buy@shop.com
df[df["colume_name"] == some_value] #Scalar, True/False..
df[df["colume_name"] == "some_value"] #String
df[(df["colume_name"] == "some_value1") & (pd[pd["colume_name"] == "some_value2"])]
pandas.notna(df["colume_name"]) == True # Not NaN
df['colume_name'].str.contains("text") # Search for "text"
df['colume_name'].str.lower().str.contains("text") # Search for "text", after converting to lowercase