szl*_*zli 1649 python dataframe pandas
如何根据pandas中某些列中的值从DataFrame中选择行?
在SQL中我会使用:
SELECT *
FROM table
WHERE colume_name = some_value
Run Code Online (Sandbox Code Playgroud)
我试着看看熊猫文档,但没有立即找到答案.
unu*_*tbu 3149
要选择列值等于标量的行some_value,请使用==:
df.loc[df['column_name'] == some_value]
Run Code Online (Sandbox Code Playgroud)
要选择列值在可迭代中的行some_values,请使用isin:
df.loc[df['column_name'].isin(some_values)]
Run Code Online (Sandbox Code Playgroud)
将多种条件与&:
df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]
Run Code Online (Sandbox Code Playgroud)
请注意括号.由于Python的运算符优先级规则,&绑定比<=和更紧密>=.因此,最后一个例子中的括号是必要的.没有括号
df['column_name'] >= A & df['column_name'] <= B
Run Code Online (Sandbox Code Playgroud)
被解析为
df['column_name'] >= (A & df['column_name']) <= B
Run Code Online (Sandbox Code Playgroud)
这导致系列的真值是一个模糊的错误.
要选择列值不相等的行 some_value,请使用!=:
df.loc[df['column_name'] != some_value]
Run Code Online (Sandbox Code Playgroud)
isin返回boolean系列,所以要选择行,其值是不是在some_values,否定使用布尔系列~:
df.loc[~df['column_name'].isin(some_values)]
Run Code Online (Sandbox Code Playgroud)
例如,
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'])
Run Code Online (Sandbox Code Playgroud)
产量
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
Run Code Online (Sandbox Code Playgroud)
如果您想要包含多个值,请将它们放在列表中(或者更常见的是,任何可迭代的)并使用isin:
print(df.loc[df['B'].isin(['one','three'])])
Run Code Online (Sandbox Code Playgroud)
产量
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
Run Code Online (Sandbox Code Playgroud)
但请注意,如果您希望多次执行此操作,则首先创建索引更有效,然后使用df.loc:
df = df.set_index(['B'])
print(df.loc['one'])
Run Code Online (Sandbox Code Playgroud)
产量
A C D
B
one foo 0 0
one bar 1 2
one foo 6 12
Run Code Online (Sandbox Code Playgroud)
或者,要包含索引使用的多个值df.index.isin:
df.loc[df.index.isin(['one','two'])]
Run Code Online (Sandbox Code Playgroud)
产量
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
Run Code Online (Sandbox Code Playgroud)
imo*_*lit 252
大熊猫相当于
select * from table where column_name = some_value
Run Code Online (Sandbox Code Playgroud)
是
table[table.column_name == some_value]
Run Code Online (Sandbox Code Playgroud)
多个条件:
table[(table.column_name == some_value) | (table.column_name2 == some_value2)]
Run Code Online (Sandbox Code Playgroud)
要么
table.query('column_name == some_value | column_name2 == some_value2')
Run Code Online (Sandbox Code Playgroud)
import pandas as pd
# Create data set
d = {'foo':[100, 111, 222],
'bar':[333, 444, 555]}
df = pd.DataFrame(d)
# Full dataframe:
df
# Shows:
# bar foo
# 0 333 100
# 1 444 111
# 2 555 222
# Output only the row(s) in df where foo is 222:
df[df.foo == 222]
# Shows:
# bar foo
# 2 555 222
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,它是在这种情况下df[df.foo == 222]基于列值给出行的行222.
多种条件也是可能的:
df[(df.foo == 222) | (df.bar == 444)]
# bar foo
# 1 444 111
# 2 555 222
Run Code Online (Sandbox Code Playgroud)
但是在那时我建议使用查询函数,因为它不那么冗长并产生相同的结果:
df.query('foo == 222 | bar == 444')
Run Code Online (Sandbox Code Playgroud)
piR*_*red 227
有一些从pandas数据框中选择行的基本方法.
对于每种基本类型,我们可以通过将自己限制在pandas API中来保持简单,或者我们可以在API之外冒险,通常进入df[df['col'] == value并加速.
我将向您展示每个示例,并指导您何时使用某些技术.
设置
我们首先需要确定一个条件,作为选择行的标准.OP提供df.iloc[...].我们将从那里开始并包含一些其他常见用例.
借用@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})
Run Code Online (Sandbox Code Playgroud)
假设我们的标准是column df.xs(...)=df.query(...)
1.
布尔索引要求查找每行的'A'列的真值等于'foo',然后使用这些真值来标识要保留的行.通常,我们将此系列命名为一系列真值,numpy.我们也会在这里这样做.
mask = df['A'] == 'foo'
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用此掩码对数据帧进行切片或索引
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
Run Code Online (Sandbox Code Playgroud)
这是完成此任务的最简单方法之一,如果性能或直观性不是问题,那么这应该是您选择的方法.但是,如果性能是一个问题,那么您可能想要考虑另一种创建方法column_name == some_value.
2.
位置索引有其用例,但这不是其中之一.为了确定切片的位置,我们首先需要执行上面我们所做的相同的布尔分析.这使我们执行一个额外的步骤来完成相同的任务.
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
4.
'A'是一种非常优雅/直观的方式来执行此任务.但往往比较慢. 但是,如果您注意以下时间,对于大数据,查询非常有效.比标准方法更重要,与我最好的建议相似.
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
Run Code Online (Sandbox Code Playgroud)
我的偏好是使用 'foo' mask
可以通过修改我们创建的方式来实现实际改进mask df.iloc[...].
df.query()alternative 1
使用底层pd.DataFrame.query数组并放弃创建另一个数组的开销Boolean
mask = df['A'].values == 'foo'
Run Code Online (Sandbox Code Playgroud)
我将在最后展示更完整的时间测试,但只是看看我们使用示例数据帧获得的性能提升.首先,我们看一下创建的区别mask
%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)
Run Code Online (Sandbox Code Playgroud)
Boolean使用mask数组进行评估的速度要快30倍.这部分是由于mask评估通常更快.部分原因还在于缺乏构建索引和相应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)
Run Code Online (Sandbox Code Playgroud)
性能提升并不明显.我们将看看这是否适用于更强大的测试.
mask替代方案2
我们也可以重建数据框架.在重建数据帧时有一个很大的警告 - 你必须mask在这样做的时候注意!
而不是numpy我们会这样做
pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)
Run Code Online (Sandbox Code Playgroud)
如果数据帧是混合类型(我们的示例是),那么当我们得到numpy结果数组pd.Series mask时,新数据帧的所有列都将是mask dtypes.因此需要df[mask]并杀死任何潜在的性能提升.
%timeit df[m]
%timeit pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)
216 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1.43 ms ± 39.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Run Code Online (Sandbox Code Playgroud)
但是,如果数据框不是混合类型,则这是一种非常有用的方法.
特定
np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))
d1
A B C D E
0 0 2 7 3 8
1 7 0 6 8 6
2 0 2 0 4 9
3 7 3 2 4 3
4 3 6 7 7 4
5 5 3 7 5 9
6 8 7 6 4 7
7 6 2 6 6 5
8 2 8 7 5 8
9 4 7 6 1 5
Run Code Online (Sandbox Code Playgroud)
%%timeit
mask = d1['A'].values == 7
d1[mask]
179 µs ± 8.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)
与
%%timeit
mask = d1['A'].values == 7
pd.DataFrame(d1.values[mask], d1.index[mask], d1.columns)
87 µs ± 5.12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)
我们把时间缩短了一半.
df.values替代3
@unutbu还向我们展示了如何使用dtype来计算object一组值中的每个元素.如果我们的值集是一个值的集合,即对此进行评估dtype.但如果需要,它还可以推广包括更大的值集.事实证明,尽管这是一个更通用的解决方案,但仍然相当快.对于那些不熟悉这个概念的人来说,唯一真正的损失是直观性的.
mask = df['A'].isin(['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
Run Code Online (Sandbox Code Playgroud)
然而,和以前一样,我们可以利用object提高性能,同时几乎不牺牲任何东西.我们会用的astype(df.dtypes)
mask = np.in1d(df['A'].values, ['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
Run Code Online (Sandbox Code Playgroud)
时间
我将包括其他帖子中提到的其他概念以供参考.
代码如下
此表中的每个列表示一个不同长度的数据框,我们在其上测试每个函数.每列显示相对时间,最快的函数给定基本索引mask.
res.div(res.min())
10 30 100 300 1000 3000 10000 30000
mask_standard 2.156872 1.850663 2.034149 2.166312 2.164541 3.090372 2.981326 3.131151
mask_standard_loc 1.879035 1.782366 1.988823 2.338112 2.361391 3.036131 2.998112 2.990103
mask_with_values 1.010166 1.000000 1.005113 1.026363 1.028698 1.293741 1.007824 1.016919
mask_with_values_loc 1.196843 1.300228 1.000000 1.000000 1.038989 1.219233 1.037020 1.000000
query 4.997304 4.765554 5.934096 4.500559 2.997924 2.397013 1.680447 1.398190
xs_label 4.124597 4.272363 5.596152 4.295331 4.676591 5.710680 6.032809 8.950255
mask_with_isin 1.674055 1.679935 1.847972 1.724183 1.345111 1.405231 1.253554 1.264760
mask_with_in1d 1.000000 1.083807 1.220493 1.101929 1.000000 1.000000 1.000000 1.144175
Run Code Online (Sandbox Code Playgroud)
你会注意到最快的时间似乎在pd.Series.isin和之间共享df['A']
res.T.plot(loglog=True)
Run Code Online (Sandbox Code Playgroud)
功能
def mask_standard(df):
mask = df['A'] == 'foo'
return df[mask]
def mask_standard_loc(df):
mask = df['A'] == 'foo'
return df.loc[mask]
def mask_with_values(df):
mask = df['A'].values == 'foo'
return df[mask]
def mask_with_values_loc(df):
mask = df['A'].values == 'foo'
return df.loc[mask]
def query(df):
return df.query('A == "foo"')
def xs_label(df):
return df.set_index('A', append=True, drop=False).xs('foo', level=-1)
def mask_with_isin(df):
mask = df['A'].isin(['foo'])
return df[mask]
def mask_with_in1d(df):
mask = np.in1d(df['A'].values, ['foo'])
return df[mask]
Run Code Online (Sandbox Code Playgroud)
测试
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)
Run Code Online (Sandbox Code Playgroud)
特殊时序
查看当我们'foo'为整个数据帧设置单个非对象时的特殊情况.
代码如下
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
Run Code Online (Sandbox Code Playgroud)
事实证明,重建不值得过去几百行.
spec.T.plot(loglog=True)
Run Code Online (Sandbox Code Playgroud)
功能
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
)
Run Code Online (Sandbox Code Playgroud)
测试
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)
Run Code Online (Sandbox Code Playgroud)
fre*_*way 54
我发现以前答案的语法是多余的,难以记住.熊猫query()在v0.13中引入了这个方法,我更喜欢它.对于你的问题,你可以做到df.query('col == val')
转载自http://pandas.pydata.org/pandas-docs/version/0.17.0/indexing.html#indexing-query
In [167]: n = 10
In [168]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))
In [169]: df
Out[169]:
a b c
0 0.687704 0.582314 0.281645
1 0.250846 0.610021 0.420121
2 0.624328 0.401816 0.932146
3 0.011763 0.022921 0.244186
4 0.590198 0.325680 0.890392
5 0.598892 0.296424 0.007312
6 0.634625 0.803069 0.123872
7 0.924168 0.325076 0.303746
8 0.116822 0.364564 0.454607
9 0.986142 0.751953 0.561512
# pure python
In [170]: df[(df.a < df.b) & (df.b < df.c)]
Out[170]:
a b c
3 0.011763 0.022921 0.244186
8 0.116822 0.364564 0.454607
# query
In [171]: df.query('(a < b) & (b < c)')
Out[171]:
a b c
3 0.011763 0.022921 0.244186
8 0.116822 0.364564 0.454607
Run Code Online (Sandbox Code Playgroud)
您还可以通过添加前导来访问环境中的变量@.
exclude = ('red', 'orange')
df.query('color not in @exclude')
Run Code Online (Sandbox Code Playgroud)
shi*_*vsn 21
使用numpy.where可以实现更快的结果.
例如,使用unubtu的设置 -
In [76]: df.iloc[np.where(df.A.values=='foo')]
Out[76]:
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
Run Code Online (Sandbox Code Playgroud)
时间比较:
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
Run Code Online (Sandbox Code Playgroud)
Dat*_*vid 19
这是一个简单的例子
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
Run Code Online (Sandbox Code Playgroud)
cot*_*ail 14
query()1. 在调用中使用 f 字符串如果用于过滤数据帧的列名称来自局部变量,则 f 字符串可能有用。例如,
\ncol = \'A\'\ndf.query(f"{col} == \'foo\'")\nRun Code Online (Sandbox Code Playgroud)\n事实上,f 字符串也可用于查询变量(日期时间除外):
\ncol = \'A\'\nmy_var = \'foo\'\ndf.query(f"{col} == \'{my_var}\'") # if my_var is a string\n\nmy_num = 1\ndf.query(f"{col} == {my_num}") # if my_var is a number\n\nmy_date = \'2022-12-10\'\ndf.query(f"{col} == @my_date") # must use @ for datetime though\nRun Code Online (Sandbox Code Playgroud)\nnumexpr以加快query()通话速度pandas 文档建议安装 numexpr以加快使用时的数值计算query()。使用pip install numexpr(或等conda,sudo具体取决于您的环境)来安装它。
对于较大的数据帧(性能实际上很重要),df.query()withnumexpr引擎的执行速度比df[mask]. 特别是对于以下情况表现更好。
字符串列上的逻辑和/或比较运算符
\n如果将一列字符串与其他一些字符串进行比较并且要选择匹配的行,即使对于单个比较操作,query()执行速度也比df[mask]. 例如,对于具有 80k 行的数据帧,速度提高了 30% 1;对于具有 800k 行的数据帧,速度提高了 60%。2
df[df.A == \'foo\']\ndf.query("A == \'foo\'") # <--- performs 30%-60% faster\nRun Code Online (Sandbox Code Playgroud)\n随着操作数量的增加(如果链接 4 个比较,df.query()速度比 1,2 快 2-2.3 倍df[mask])1,2和/或数据帧长度增加,此差距也会增加。2
对数字列进行多种操作
\n如果需要计算多个算术、逻辑或比较运算来创建布尔掩码以进行过滤df,query()则执行速度会更快。例如,对于具有 80k 行的帧,速度快 20% 1;对于具有 800k 行的帧,速度快 2 倍。2
df[(df.B % 5) **2 < 0.1]\ndf.query("(B % 5) **2 < 0.1") # <--- performs 20%-100% faster.\nRun Code Online (Sandbox Code Playgroud)\n随着操作数量的增加和/或数据帧长度的增加,这种性能差距也会增加。2
\n下图显示了随着数据帧长度的增加,这些方法的执行情况。3
\n\nquery()Numexpr 目前仅支持逻辑运算符 ( &, |, ~)、比较运算符 ( ==, >, <, >=, <=, !=) 和基本算术运算符 ( +, -, *, /, **, %)。
例如,它不支持整数除法 ( //)。然而,调用等效的 pandas 方法 ( floordiv()) 是有效的。
df.query(\'B.floordiv(2) <= 3\') # or \ndf.query(\'B.floordiv(2).le(3)\')\n\n# for pandas < 1.4, need `.values`\ndf.query(\'B.floordiv(2).values <= 3\')\nRun Code Online (Sandbox Code Playgroud)\n 1使用 80k 行帧的基准代码
\nimport numpy as np\ndf = pd.DataFrame({\'A\': \'foo bar foo baz foo bar foo foo\'.split()*10000, \n \'B\': np.random.rand(80000)})\n\n%timeit df[df.A == \'foo\']\n# 8.5 ms \xc2\xb1 104.5 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n%timeit df.query("A == \'foo\'")\n# 6.36 ms \xc2\xb1 95.7 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n\n%timeit df[((df.A == \'foo\') & (df.A != \'bar\')) | ((df.A != \'baz\') & (df.A != \'buz\'))]\n# 29 ms \xc2\xb1 554 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 10 runs, 100 loops each)\n%timeit df.query("A == \'foo\' & A != \'bar\' | A != \'baz\' & A != \'buz\'")\n# 16 ms \xc2\xb1 339 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 10 runs, 100 loops each)\n\n%timeit df[(df.B % 5) **2 < 0.1]\n# 5.35 ms \xc2\xb1 37.6 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n%timeit df.query("(B % 5) **2 < 0.1")\n# 4.37 ms \xc2\xb1 46.3 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\nRun Code Online (Sandbox Code Playgroud)\n2使用 800k 行帧的基准代码
\ndf = pd.DataFrame({\'A\': \'foo bar foo baz foo bar foo foo\'.split()*100000, \n \'B\': np.random.rand(800000)})\n\n%timeit df[df.A == \'foo\']\n# 87.9 ms \xc2\xb1 873 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 10 runs, 100 loops each)\n%timeit df.query("A == \'foo\'")\n# 54.4 ms \xc2\xb1 726 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 10 runs, 100 loops each)\n\n%timeit df[((df.A == \'foo\') & (df.A != \'bar\')) | ((df.A != \'baz\') & (df.A != \'buz\'))]\n# 310 ms \xc2\xb1 3.4 ms per loop (mean \xc2\xb1 std. dev. of 10 runs, 100 loops each)\n%timeit df.query("A == \'foo\' & A != \'bar\' | A != \'baz\' & A != \'buz\'")\n# 132 ms \xc2\xb1 2.43 ms per loop (mean \xc2\xb1 std. dev. of 10 runs, 100 loops each)\n\n%timeit df[(df.B % 5) **2 < 0.1]\n# 54 ms \xc2\xb1 488 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 10 runs, 100 loops each)\n%timeit df.query("(B % 5) **2 < 0.1")\n# 26.3 ms \xc2\xb1 320 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 10 runs, 100 loops each)\nRun Code Online (Sandbox Code Playgroud)\n3:用于生成字符串和数字两种方法的性能图的代码。
\nfrom perfplot import plot\nconstructor = lambda n: pd.DataFrame({\'A\': \'foo bar foo baz foo bar foo foo\'.split()*n, \'B\': np.random.rand(8*n)})\nplot(\n setup=constructor,\n kernels=[lambda df: df[(df.B%5)**2<0.1], lambda df: df.query("(B%5)**2<0.1")],\n labels= [\'df[(df.B % 5) **2 < 0.1]\', \'df.query("(B % 5) **2 < 0.1")\'],\n n_range=[2**k for k in range(4, 24)],\n xlabel=\'Rows in DataFrame\',\n title=\'Multiple mathematical operations on numbers\',\n equality_check=pd.DataFrame.equals);\nplot(\n setup=constructor,\n kernels=[lambda df: df[df.A == \'foo\'], lambda df: df.query("A == \'foo\'")],\n labels= ["df[df.A == \'foo\']", """df.query("A == \'foo\'")"""],\n n_range=[2**k for k in range(4, 24)],\n xlabel=\'Rows in DataFrame\',\n title=\'Comparison operation on strings\',\n equality_check=pd.DataFrame.equals);\nRun Code Online (Sandbox Code Playgroud)\n
SP0*_*001 13
对于pandas中的给定值,仅从多列中选择特定列:
select col_name1, col_name2 from table where column_name = some_value.
Run Code Online (Sandbox Code Playgroud)
选项:
df.loc[df['column_name'] == some_value][[col_name1, col_name2]]
Run Code Online (Sandbox Code Playgroud)
要么
df.query['column_name' == 'some_value'][[col_name1, col_name2]]
Run Code Online (Sandbox Code Playgroud)
Erf*_*fan 11
.query具有更大的灵活性pandas >= 0.25.0:2019年8月更新的答案
因为pandas >= 0.25.0我们可以使用querypandas方法甚至带空格的列名称来使用该方法过滤数据帧。通常,列名中的空格会产生错误,但是现在我们可以使用反引号(`)来解决该问题,请参见GitHub:
# 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
Run Code Online (Sandbox Code Playgroud)
使用.querywith方法str.endswith:
df.query('`Sender email`.str.endswith("@shop.com")')
Run Code Online (Sandbox Code Playgroud)
输出量
Sender email
1 reply@shop.com
2 buy@shop.com
Run Code Online (Sandbox Code Playgroud)
同样,我们可以@在查询中以前缀作为局部变量来使用局部变量:
domain = 'shop.com'
df.query('`Sender email`.str.endswith(@domain)')
Run Code Online (Sandbox Code Playgroud)
输出量
Sender email
1 reply@shop.com
2 buy@shop.com
Run Code Online (Sandbox Code Playgroud)
Tua*_*nDT 10
要附加到这个着名的问题(虽然有点太晚了):您还可以df.groupby('column_name').get_group('column_desired_value').reset_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)
Run Code Online (Sandbox Code Playgroud)
运行此给出:
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
Run Code Online (Sandbox Code Playgroud)
您还可以使用 .apply:
df.apply(lambda row: row[df['B'].isin(['one','three'])])
Run Code Online (Sandbox Code Playgroud)
它实际上是按行工作的(即,将函数应用于每一行)。
输出是
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
Run Code Online (Sandbox Code Playgroud)
结果与@unutbu 提到的使用相同
df[[df['B'].isin(['one','three'])]]
Run Code Online (Sandbox Code Playgroud)
在较新版本的 Pandas 中,受文档(查看数据)启发:
df[df["colume_name"] == some_value] #Scalar, True/False..
df[df["colume_name"] == "some_value"] #String
Run Code Online (Sandbox Code Playgroud)
通过将子句放在括号中来组合多个条件,并将()它们与&和|(和/或)组合。像这样:
df[(df["colume_name"] == "some_value1") & (pd[pd["colume_name"] == "some_value2"])]
Run Code Online (Sandbox Code Playgroud)
其他过滤器
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
Run Code Online (Sandbox Code Playgroud)
小智 5
如果您想重复查询数据帧并且速度对您很重要,最好的办法是将数据帧转换为字典,然后通过这样做,您可以使查询速度加快数千倍。
my_df = df.set_index(column_name)
my_dict = my_df.to_dict('index')
Run Code Online (Sandbox Code Playgroud)
创建 my_dict 字典后,您可以通过:
if some_value in my_dict.keys():
my_result = my_dict[some_value]
Run Code Online (Sandbox Code Playgroud)
如果column_name中有重复的值,则无法创建字典。但你可以使用:
my_result = my_df.loc[some_value]
Run Code Online (Sandbox Code Playgroud)
使用DuckDB,我们可以使用 SQL 语句以高性能的方式查询 pandas DataFrame 。
由于问题是如何根据列值从 DataFrame 中选择行?,问题中的示例是 SQL 查询,这个答案在本主题中看起来很合乎逻辑。
例子:
In [1]: import duckdb
In [2]: import pandas as pd
In [3]: con = duckdb.connect()
In [4]: df = pd.DataFrame({"A": range(11), "B": range(11, 22)})
In [5]: df
Out[5]:
A B
0 0 11
1 1 12
2 2 13
3 3 14
4 4 15
5 5 16
6 6 17
7 7 18
8 8 19
9 9 20
10 10 21
In [6]: results = con.execute("SELECT * FROM df where A > 2").df()
In [7]: results
Out[7]:
A B
0 3 14
1 4 15
2 5 16
3 6 17
4 7 18
5 8 19
6 9 20
7 10 21
Run Code Online (Sandbox Code Playgroud)
您可以将loc(方括号)与函数一起使用:
# Series
s = pd.Series([1, 2, 3, 4])
s.loc[lambda x: x > 1]
# s[lambda x: x > 1]
Run Code Online (Sandbox Code Playgroud)
输出:
1 2
2 3
3 4
dtype: int64
Run Code Online (Sandbox Code Playgroud)
或者
# DataFrame
df = pd.DataFrame({'A': [1, 2, 3], 'B': [10, 20, 30]})
df[lambda x: (x['A'] != 1) & (x['B'] != 30)]
Run Code Online (Sandbox Code Playgroud)
输出:
A B
1 2 20
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2303550 次 |
| 最近记录: |