Pandas 2.2 中文官方教程和指南(十一·二)(3)

简介: Pandas 2.2 中文官方教程和指南(十一·二)

Pandas 2.2 中文官方教程和指南(十一·二)(2)https://developer.aliyun.com/article/1509870

query() 方法

DataFrame 对象具有一个允许使用表达式进行选择的 query() 方法。

你可以获取列b的值在列ac的值之间的帧的值。例如:

In [226]: n = 10
In [227]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))
In [228]: df
Out[228]: 
 a         b         c
0  0.438921  0.118680  0.863670
1  0.138138  0.577363  0.686602
2  0.595307  0.564592  0.520630
3  0.913052  0.926075  0.616184
4  0.078718  0.854477  0.898725
5  0.076404  0.523211  0.591538
6  0.792342  0.216974  0.564056
7  0.397890  0.454131  0.915716
8  0.074315  0.437913  0.019794
9  0.559209  0.502065  0.026437
# pure python
In [229]: df[(df['a'] < df['b']) & (df['b'] < df['c'])]
Out[229]: 
 a         b         c
1  0.138138  0.577363  0.686602
4  0.078718  0.854477  0.898725
5  0.076404  0.523211  0.591538
7  0.397890  0.454131  0.915716
# query
In [230]: df.query('(a < b) & (b < c)')
Out[230]: 
 a         b         c
1  0.138138  0.577363  0.686602
4  0.078718  0.854477  0.898725
5  0.076404  0.523211  0.591538
7  0.397890  0.454131  0.915716 

做同样的事情,但如果没有名为 a 的列,则回退到命名索引。

In [231]: df = pd.DataFrame(np.random.randint(n / 2, size=(n, 2)), columns=list('bc'))
In [232]: df.index.name = 'a'
In [233]: df
Out[233]: 
 b  c
a 
0  0  4
1  0  1
2  3  4
3  4  3
4  1  4
5  0  3
6  0  1
7  3  4
8  2  3
9  1  1
In [234]: df.query('a < b and b < c')
Out[234]: 
 b  c
a 
2  3  4 

如果你不想或不能命名你的索引,你可以在查询表达式中使用名称index

In [235]: df = pd.DataFrame(np.random.randint(n, size=(n, 2)), columns=list('bc'))
In [236]: df
Out[236]: 
 b  c
0  3  1
1  3  0
2  5  6
3  5  2
4  7  4
5  0  1
6  2  5
7  0  1
8  6  0
9  7  9
In [237]: df.query('index < b < c')
Out[237]: 
 b  c
2  5  6 

注意

如果你的索引名称与列名重叠,列名将优先考虑。例如,

In [238]: df = pd.DataFrame({'a': np.random.randint(5, size=5)})
In [239]: df.index.name = 'a'
In [240]: df.query('a > 2')  # uses the column 'a', not the index
Out[240]: 
 a
a 
1  3
3  3 

你仍然可以通过使用特殊标识符‘index’在查询表达式中使用索引:

In [241]: df.query('index > 2')
Out[241]: 
 a
a 
3  3
4  2 

如果因某种原因你有一个名为index的列,那么你也可以将索引称为ilevel_0,但此时你应考虑将列重命名为更少歧义的名称。

MultiIndex query() 语法

你也可以像操作列一样使用带有 MultiIndexDataFrame 的级别:

In [242]: n = 10
In [243]: colors = np.random.choice(['red', 'green'], size=n)
In [244]: foods = np.random.choice(['eggs', 'ham'], size=n)
In [245]: colors
Out[245]: 
array(['red', 'red', 'red', 'green', 'green', 'green', 'green', 'green',
 'green', 'green'], dtype='<U5')
In [246]: foods
Out[246]: 
array(['ham', 'ham', 'eggs', 'eggs', 'eggs', 'ham', 'ham', 'eggs', 'eggs',
 'eggs'], dtype='<U4')
In [247]: index = pd.MultiIndex.from_arrays([colors, foods], names=['color', 'food'])
In [248]: df = pd.DataFrame(np.random.randn(n, 2), index=index)
In [249]: df
Out[249]: 
 0         1
color food 
red   ham   0.194889 -0.381994
 ham   0.318587  2.089075
 eggs -0.728293 -0.090255
green eggs -0.748199  1.318931
 eggs -2.029766  0.792652
 ham   0.461007 -0.542749
 ham  -0.305384 -0.479195
 eggs  0.095031 -0.270099
 eggs -0.707140 -0.773882
 eggs  0.229453  0.304418
In [250]: df.query('color == "red"')
Out[250]: 
 0         1
color food 
red   ham   0.194889 -0.381994
 ham   0.318587  2.089075
 eggs -0.728293 -0.090255 

如果 MultiIndex 的级别没有命名,你可以使用特殊名称来引用它们:

In [251]: df.index.names = [None, None]
In [252]: df
Out[252]: 
 0         1
red   ham   0.194889 -0.381994
 ham   0.318587  2.089075
 eggs -0.728293 -0.090255
green eggs -0.748199  1.318931
 eggs -2.029766  0.792652
 ham   0.461007 -0.542749
 ham  -0.305384 -0.479195
 eggs  0.095031 -0.270099
 eggs -0.707140 -0.773882
 eggs  0.229453  0.304418
In [253]: df.query('ilevel_0 == "red"')
Out[253]: 
 0         1
red ham   0.194889 -0.381994
 ham   0.318587  2.089075
 eggs -0.728293 -0.090255 

约定是 ilevel_0,表示“索引级别 0”对应索引的第 0 级。

query() 用例

query() 的一个用例是当你有一组具有共同列名(或索引级别/名称)子集的 DataFrame 对象时。你可以将相同的查询传递给两个框架,而不必指定你要查询的框架

In [254]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))
In [255]: df
Out[255]: 
 a         b         c
0  0.224283  0.736107  0.139168
1  0.302827  0.657803  0.713897
2  0.611185  0.136624  0.984960
3  0.195246  0.123436  0.627712
4  0.618673  0.371660  0.047902
5  0.480088  0.062993  0.185760
6  0.568018  0.483467  0.445289
7  0.309040  0.274580  0.587101
8  0.258993  0.477769  0.370255
9  0.550459  0.840870  0.304611
In [256]: df2 = pd.DataFrame(np.random.rand(n + 2, 3), columns=df.columns)
In [257]: df2
Out[257]: 
 a         b         c
0   0.357579  0.229800  0.596001
1   0.309059  0.957923  0.965663
2   0.123102  0.336914  0.318616
3   0.526506  0.323321  0.860813
4   0.518736  0.486514  0.384724
5   0.190804  0.505723  0.614533
6   0.891939  0.623977  0.676639
7   0.480559  0.378528  0.460858
8   0.420223  0.136404  0.141295
9   0.732206  0.419540  0.604675
10  0.604466  0.848974  0.896165
11  0.589168  0.920046  0.732716
In [258]: expr = '0.0 <= a <= c <= 0.5'
In [259]: map(lambda frame: frame.query(expr), [df, df2])
Out[259]: <map at 0x7ff2e57db2e0> 

query() Python 与 pandas 语法比较

完整的类似 numpy 的语法:

In [260]: df = pd.DataFrame(np.random.randint(n, size=(n, 3)), columns=list('abc'))
In [261]: df
Out[261]: 
 a  b  c
0  7  8  9
1  1  0  7
2  2  7  2
3  6  2  2
4  2  6  3
5  3  8  2
6  1  7  2
7  5  1  5
8  9  8  0
9  1  5  0
In [262]: df.query('(a < b) & (b < c)')
Out[262]: 
 a  b  c
0  7  8  9
In [263]: df[(df['a'] < df['b']) & (df['b'] < df['c'])]
Out[263]: 
 a  b  c
0  7  8  9 

稍微优化一下,去掉括号(比较运算符比 &| 的优先级更高):

In [264]: df.query('a < b & b < c')
Out[264]: 
 a  b  c
0  7  8  9 

使用英语而不是符号:

In [265]: df.query('a < b and b < c')
Out[265]: 
 a  b  c
0  7  8  9 

与您可能在纸上写的方式非常接近:

In [266]: df.query('a < b < c')
Out[266]: 
 a  b  c
0  7  8  9 

innot in运算符

query()还支持 Python 的innot in比较运算符的特殊用法,提供了一种简洁的语法来调用SeriesDataFrameisin方法。

# get all rows where columns "a" and "b" have overlapping values
In [267]: df = pd.DataFrame({'a': list('aabbccddeeff'), 'b': list('aaaabbbbcccc'),
 .....:                   'c': np.random.randint(5, size=12),
 .....:                   'd': np.random.randint(9, size=12)})
 .....: 
In [268]: df
Out[268]: 
 a  b  c  d
0   a  a  2  6
1   a  a  4  7
2   b  a  1  6
3   b  a  2  1
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2
In [269]: df.query('a in b')
Out[269]: 
 a  b  c  d
0  a  a  2  6
1  a  a  4  7
2  b  a  1  6
3  b  a  2  1
4  c  b  3  6
5  c  b  0  2
# How you'd do it in pure Python
In [270]: df[df['a'].isin(df['b'])]
Out[270]: 
 a  b  c  d
0  a  a  2  6
1  a  a  4  7
2  b  a  1  6
3  b  a  2  1
4  c  b  3  6
5  c  b  0  2
In [271]: df.query('a not in b')
Out[271]: 
 a  b  c  d
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2
# pure Python
In [272]: df[~df['a'].isin(df['b'])]
Out[272]: 
 a  b  c  d
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2 

您可以将此与其他表达式结合使用,以获得非常简洁的查询:

# rows where cols a and b have overlapping values
# and col c's values are less than col d's
In [273]: df.query('a in b and c < d')
Out[273]: 
 a  b  c  d
0  a  a  2  6
1  a  a  4  7
2  b  a  1  6
4  c  b  3  6
5  c  b  0  2
# pure Python
In [274]: df[df['b'].isin(df['a']) & (df['c'] < df['d'])]
Out[274]: 
 a  b  c  d
0   a  a  2  6
1   a  a  4  7
2   b  a  1  6
4   c  b  3  6
5   c  b  0  2
10  f  c  0  6
11  f  c  1  2 

注意

请注意,innot in在 Python 中进行评估,因为numexpr没有这个操作的等效操作。但是,只有in/not in 表达式本身在普通 Python 中进行评估。例如,在表达式中

df.query('a in b + c + d') 

(b + c + d)numexpr计算,然后在普通 Python 中评估in操作。一般来说,任何可以使用numexpr计算的操作都会被计算。

==运算符与list对象的特殊用法

使用==/!=将值列表与列进行比较与使用in/not in类似。

In [275]: df.query('b == ["a", "b", "c"]')
Out[275]: 
 a  b  c  d
0   a  a  2  6
1   a  a  4  7
2   b  a  1  6
3   b  a  2  1
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2
# pure Python
In [276]: df[df['b'].isin(["a", "b", "c"])]
Out[276]: 
 a  b  c  d
0   a  a  2  6
1   a  a  4  7
2   b  a  1  6
3   b  a  2  1
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2
In [277]: df.query('c == [1, 2]')
Out[277]: 
 a  b  c  d
0   a  a  2  6
2   b  a  1  6
3   b  a  2  1
7   d  b  2  1
9   e  c  2  0
11  f  c  1  2
In [278]: df.query('c != [1, 2]')
Out[278]: 
 a  b  c  d
1   a  a  4  7
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
8   e  c  4  3
10  f  c  0  6
# using in/not in
In [279]: df.query('[1, 2] in c')
Out[279]: 
 a  b  c  d
0   a  a  2  6
2   b  a  1  6
3   b  a  2  1
7   d  b  2  1
9   e  c  2  0
11  f  c  1  2
In [280]: df.query('[1, 2] not in c')
Out[280]: 
 a  b  c  d
1   a  a  4  7
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
8   e  c  4  3
10  f  c  0  6
# pure Python
In [281]: df[df['c'].isin([1, 2])]
Out[281]: 
 a  b  c  d
0   a  a  2  6
2   b  a  1  6
3   b  a  2  1
7   d  b  2  1
9   e  c  2  0
11  f  c  1  2 

布尔运算符

你可以用not~运算符来否定布尔表达式。

In [282]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))
In [283]: df['bools'] = np.random.rand(len(df)) > 0.5
In [284]: df.query('~bools')
Out[284]: 
 a         b         c  bools
2  0.697753  0.212799  0.329209  False
7  0.275396  0.691034  0.826619  False
8  0.190649  0.558748  0.262467  False
In [285]: df.query('not bools')
Out[285]: 
 a         b         c  bools
2  0.697753  0.212799  0.329209  False
7  0.275396  0.691034  0.826619  False
8  0.190649  0.558748  0.262467  False
In [286]: df.query('not bools') == df[~df['bools']]
Out[286]: 
 a     b     c  bools
2  True  True  True   True
7  True  True  True   True
8  True  True  True   True 

当然,表达式也可以任意复杂:

# short query syntax
In [287]: shorter = df.query('a < b < c and (not bools) or bools > 2')
# equivalent in pure Python
In [288]: longer = df[(df['a'] < df['b'])
 .....:            & (df['b'] < df['c'])
 .....:            & (~df['bools'])
 .....:            | (df['bools'] > 2)]
 .....: 
In [289]: shorter
Out[289]: 
 a         b         c  bools
7  0.275396  0.691034  0.826619  False
In [290]: longer
Out[290]: 
 a         b         c  bools
7  0.275396  0.691034  0.826619  False
In [291]: shorter == longer
Out[291]: 
 a     b     c  bools
7  True  True  True   True 

query()的性能

对于大框架,使用numexprDataFrame.query()比 Python 略快。

只有当您的框架超过大约 100,000 行时,才能看到使用numexpr引擎与DataFrame.query()的性能优势。

这个图是使用包含 3 列的DataFrame创建的,每列都包含使用numpy.random.randn()生成的浮点值。

In [292]: df = pd.DataFrame(np.random.randn(8, 4),
 .....:                  index=dates, columns=['A', 'B', 'C', 'D'])
 .....: 
In [293]: df2 = df.copy() 

MultiIndex query() 语法

您还可以像在框架中的列一样使用DataFrameMultiIndex的级别:

In [242]: n = 10
In [243]: colors = np.random.choice(['red', 'green'], size=n)
In [244]: foods = np.random.choice(['eggs', 'ham'], size=n)
In [245]: colors
Out[245]: 
array(['red', 'red', 'red', 'green', 'green', 'green', 'green', 'green',
 'green', 'green'], dtype='<U5')
In [246]: foods
Out[246]: 
array(['ham', 'ham', 'eggs', 'eggs', 'eggs', 'ham', 'ham', 'eggs', 'eggs',
 'eggs'], dtype='<U4')
In [247]: index = pd.MultiIndex.from_arrays([colors, foods], names=['color', 'food'])
In [248]: df = pd.DataFrame(np.random.randn(n, 2), index=index)
In [249]: df
Out[249]: 
 0         1
color food 
red   ham   0.194889 -0.381994
 ham   0.318587  2.089075
 eggs -0.728293 -0.090255
green eggs -0.748199  1.318931
 eggs -2.029766  0.792652
 ham   0.461007 -0.542749
 ham  -0.305384 -0.479195
 eggs  0.095031 -0.270099
 eggs -0.707140 -0.773882
 eggs  0.229453  0.304418
In [250]: df.query('color == "red"')
Out[250]: 
 0         1
color food 
red   ham   0.194889 -0.381994
 ham   0.318587  2.089075
 eggs -0.728293 -0.090255 

如果MultiIndex的级别没有名称,您可以使用特殊名称引用它们:

In [251]: df.index.names = [None, None]
In [252]: df
Out[252]: 
 0         1
red   ham   0.194889 -0.381994
 ham   0.318587  2.089075
 eggs -0.728293 -0.090255
green eggs -0.748199  1.318931
 eggs -2.029766  0.792652
 ham   0.461007 -0.542749
 ham  -0.305384 -0.479195
 eggs  0.095031 -0.270099
 eggs -0.707140 -0.773882
 eggs  0.229453  0.304418
In [253]: df.query('ilevel_0 == "red"')
Out[253]: 
 0         1
red ham   0.194889 -0.381994
 ham   0.318587  2.089075
 eggs -0.728293 -0.090255 

约定是ilevel_0,表示“索引级别 0”对应index的第 0 级。

query()用例

query()的一个用例是当你有一组具有共同列名(或索引级别/名称)子集的DataFrame对象时。你可以将相同的查询传递给两个框架,而不需要指定你要查询的框架。

In [254]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))
In [255]: df
Out[255]: 
 a         b         c
0  0.224283  0.736107  0.139168
1  0.302827  0.657803  0.713897
2  0.611185  0.136624  0.984960
3  0.195246  0.123436  0.627712
4  0.618673  0.371660  0.047902
5  0.480088  0.062993  0.185760
6  0.568018  0.483467  0.445289
7  0.309040  0.274580  0.587101
8  0.258993  0.477769  0.370255
9  0.550459  0.840870  0.304611
In [256]: df2 = pd.DataFrame(np.random.rand(n + 2, 3), columns=df.columns)
In [257]: df2
Out[257]: 
 a         b         c
0   0.357579  0.229800  0.596001
1   0.309059  0.957923  0.965663
2   0.123102  0.336914  0.318616
3   0.526506  0.323321  0.860813
4   0.518736  0.486514  0.384724
5   0.190804  0.505723  0.614533
6   0.891939  0.623977  0.676639
7   0.480559  0.378528  0.460858
8   0.420223  0.136404  0.141295
9   0.732206  0.419540  0.604675
10  0.604466  0.848974  0.896165
11  0.589168  0.920046  0.732716
In [258]: expr = '0.0 <= a <= c <= 0.5'
In [259]: map(lambda frame: frame.query(expr), [df, df2])
Out[259]: <map at 0x7ff2e57db2e0> 

query() Python 与 pandas 语法比较

完全类似于 numpy 的语法:

In [260]: df = pd.DataFrame(np.random.randint(n, size=(n, 3)), columns=list('abc'))
In [261]: df
Out[261]: 
 a  b  c
0  7  8  9
1  1  0  7
2  2  7  2
3  6  2  2
4  2  6  3
5  3  8  2
6  1  7  2
7  5  1  5
8  9  8  0
9  1  5  0
In [262]: df.query('(a < b) & (b < c)')
Out[262]: 
 a  b  c
0  7  8  9
In [263]: df[(df['a'] < df['b']) & (df['b'] < df['c'])]
Out[263]: 
 a  b  c
0  7  8  9 

通过删除括号(比较运算符比&|更紧密)稍微更好一点:

In [264]: df.query('a < b & b < c')
Out[264]: 
 a  b  c
0  7  8  9 

使用英文而不是符号:

In [265]: df.query('a < b and b < c')
Out[265]: 
 a  b  c
0  7  8  9 

与您可能在纸上书写的方式非常接近:

In [266]: df.query('a < b < c')
Out[266]: 
 a  b  c
0  7  8  9 

innot in运算符

query()还支持对 Python 的innot in比较运算符的特殊用法,提供了对SeriesDataFrameisin方法的简洁语法。

# get all rows where columns "a" and "b" have overlapping values
In [267]: df = pd.DataFrame({'a': list('aabbccddeeff'), 'b': list('aaaabbbbcccc'),
 .....:                   'c': np.random.randint(5, size=12),
 .....:                   'd': np.random.randint(9, size=12)})
 .....: 
In [268]: df
Out[268]: 
 a  b  c  d
0   a  a  2  6
1   a  a  4  7
2   b  a  1  6
3   b  a  2  1
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2
In [269]: df.query('a in b')
Out[269]: 
 a  b  c  d
0  a  a  2  6
1  a  a  4  7
2  b  a  1  6
3  b  a  2  1
4  c  b  3  6
5  c  b  0  2
# How you'd do it in pure Python
In [270]: df[df['a'].isin(df['b'])]
Out[270]: 
 a  b  c  d
0  a  a  2  6
1  a  a  4  7
2  b  a  1  6
3  b  a  2  1
4  c  b  3  6
5  c  b  0  2
In [271]: df.query('a not in b')
Out[271]: 
 a  b  c  d
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2
# pure Python
In [272]: df[~df['a'].isin(df['b'])]
Out[272]: 
 a  b  c  d
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2 

您可以将其与其他表达式组合以得到非常简洁的查询:

# rows where cols a and b have overlapping values
# and col c's values are less than col d's
In [273]: df.query('a in b and c < d')
Out[273]: 
 a  b  c  d
0  a  a  2  6
1  a  a  4  7
2  b  a  1  6
4  c  b  3  6
5  c  b  0  2
# pure Python
In [274]: df[df['b'].isin(df['a']) & (df['c'] < df['d'])]
Out[274]: 
 a  b  c  d
0   a  a  2  6
1   a  a  4  7
2   b  a  1  6
4   c  b  3  6
5   c  b  0  2
10  f  c  0  6
11  f  c  1  2 

注意

请注意,由于numexpr没有此操作的等效操作,因此innot in在 Python 中进行评估。但是,仅在原始的in/not in表达式本身在普通 Python 中进行评估。例如,在表达式中

df.query('a in b + c + d') 

(b + c + d)numexpr评估,然后使用普通 Python 评估in操作。一般来说,任何可以使用numexpr评估的操作都将被评估。

list对象一起使用==运算符的特殊用法

使用==/!=将值列表与列进行比较与使用in/not in类似。

In [275]: df.query('b == ["a", "b", "c"]')
Out[275]: 
 a  b  c  d
0   a  a  2  6
1   a  a  4  7
2   b  a  1  6
3   b  a  2  1
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2
# pure Python
In [276]: df[df['b'].isin(["a", "b", "c"])]
Out[276]: 
 a  b  c  d
0   a  a  2  6
1   a  a  4  7
2   b  a  1  6
3   b  a  2  1
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
7   d  b  2  1
8   e  c  4  3
9   e  c  2  0
10  f  c  0  6
11  f  c  1  2
In [277]: df.query('c == [1, 2]')
Out[277]: 
 a  b  c  d
0   a  a  2  6
2   b  a  1  6
3   b  a  2  1
7   d  b  2  1
9   e  c  2  0
11  f  c  1  2
In [278]: df.query('c != [1, 2]')
Out[278]: 
 a  b  c  d
1   a  a  4  7
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
8   e  c  4  3
10  f  c  0  6
# using in/not in
In [279]: df.query('[1, 2] in c')
Out[279]: 
 a  b  c  d
0   a  a  2  6
2   b  a  1  6
3   b  a  2  1
7   d  b  2  1
9   e  c  2  0
11  f  c  1  2
In [280]: df.query('[1, 2] not in c')
Out[280]: 
 a  b  c  d
1   a  a  4  7
4   c  b  3  6
5   c  b  0  2
6   d  b  3  3
8   e  c  4  3
10  f  c  0  6
# pure Python
In [281]: df[df['c'].isin([1, 2])]
Out[281]: 
 a  b  c  d
0   a  a  2  6
2   b  a  1  6
3   b  a  2  1
7   d  b  2  1
9   e  c  2  0
11  f  c  1  2 

布尔运算符

您可以使用单词not~运算符否定布尔表达式。

In [282]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))
In [283]: df['bools'] = np.random.rand(len(df)) > 0.5
In [284]: df.query('~bools')
Out[284]: 
 a         b         c  bools
2  0.697753  0.212799  0.329209  False
7  0.275396  0.691034  0.826619  False
8  0.190649  0.558748  0.262467  False
In [285]: df.query('not bools')
Out[285]: 
 a         b         c  bools
2  0.697753  0.212799  0.329209  False
7  0.275396  0.691034  0.826619  False
8  0.190649  0.558748  0.262467  False
In [286]: df.query('not bools') == df[~df['bools']]
Out[286]: 
 a     b     c  bools
2  True  True  True   True
7  True  True  True   True
8  True  True  True   True 

当然,表达式也可以任意复杂:

# short query syntax
In [287]: shorter = df.query('a < b < c and (not bools) or bools > 2')
# equivalent in pure Python
In [288]: longer = df[(df['a'] < df['b'])
 .....:            & (df['b'] < df['c'])
 .....:            & (~df['bools'])
 .....:            | (df['bools'] > 2)]
 .....: 
In [289]: shorter
Out[289]: 
 a         b         c  bools
7  0.275396  0.691034  0.826619  False
In [290]: longer
Out[290]: 
 a         b         c  bools
7  0.275396  0.691034  0.826619  False
In [291]: shorter == longer
Out[291]: 
 a     b     c  bools
7  True  True  True   True 

query()的性能

使用numexprDataFrame.query()对于大型数据框而言略快于 Python。

只有当您的数据框中的行数超过约100,000行时,使用numexpr引擎的DataFrame.query()才会显示性能优势。

此图是使用每个包含使用numpy.random.randn()生成的浮点值的 3 列 DataFrame 创建的。

In [292]: df = pd.DataFrame(np.random.randn(8, 4),
 .....:                  index=dates, columns=['A', 'B', 'C', 'D'])
 .....: 
In [293]: df2 = df.copy() 

重复数据

如果您想要在 DataFrame 中标识并删除重复行,有两种方法可以帮助:duplicateddrop_duplicates。每个方法都以用于标识重复行的列作为参数。

  • duplicated返回一个布尔向量,其长度为行数,指示行是否重复。
  • drop_duplicates会删除重复的行。

默认情况下,重复集的第一个观察到的行被视为唯一,但是每种方法都有一个keep参数来指定要保留的目标。

  • keep='first'(默认):标记/丢弃重复项,除了第一次出现的情况。
  • keep='last':标记/丢弃重复项,除了最后一次出现的情况。
  • keep=False:标记/删除所有重复项。
In [294]: df2 = pd.DataFrame({'a': ['one', 'one', 'two', 'two', 'two', 'three', 'four'],
 .....:                    'b': ['x', 'y', 'x', 'y', 'x', 'x', 'x'],
 .....:                    'c': np.random.randn(7)})
 .....: 
In [295]: df2
Out[295]: 
 a  b         c
0    one  x -1.067137
1    one  y  0.309500
2    two  x -0.211056
3    two  y -1.842023
4    two  x -0.390820
5  three  x -1.964475
6   four  x  1.298329
In [296]: df2.duplicated('a')
Out[296]: 
0    False
1     True
2    False
3     True
4     True
5    False
6    False
dtype: bool
In [297]: df2.duplicated('a', keep='last')
Out[297]: 
0     True
1    False
2     True
3     True
4    False
5    False
6    False
dtype: bool
In [298]: df2.duplicated('a', keep=False)
Out[298]: 
0     True
1     True
2     True
3     True
4     True
5    False
6    False
dtype: bool
In [299]: df2.drop_duplicates('a')
Out[299]: 
 a  b         c
0    one  x -1.067137
2    two  x -0.211056
5  three  x -1.964475
6   four  x  1.298329
In [300]: df2.drop_duplicates('a', keep='last')
Out[300]: 
 a  b         c
1    one  y  0.309500
4    two  x -0.390820
5  three  x -1.964475
6   four  x  1.298329
In [301]: df2.drop_duplicates('a', keep=False)
Out[301]: 
 a  b         c
5  three  x -1.964475
6   four  x  1.298329 

此外,您可以传递列的列表来标识重复项。

In [302]: df2.duplicated(['a', 'b'])
Out[302]: 
0    False
1    False
2    False
3    False
4     True
5    False
6    False
dtype: bool
In [303]: df2.drop_duplicates(['a', 'b'])
Out[303]: 
 a  b         c
0    one  x -1.067137
1    one  y  0.309500
2    two  x -0.211056
3    two  y -1.842023
5  three  x -1.964475
6   four  x  1.298329 

要通过索引值删除重复项,请使用Index.duplicated然后执行切片。keep参数可用于相同的选项集。

In [304]: df3 = pd.DataFrame({'a': np.arange(6),
 .....:                    'b': np.random.randn(6)},
 .....:                   index=['a', 'a', 'b', 'c', 'b', 'a'])
 .....: 
In [305]: df3
Out[305]: 
 a         b
a  0  1.440455
a  1  2.456086
b  2  1.038402
c  3 -0.894409
b  4  0.683536
a  5  3.082764
In [306]: df3.index.duplicated()
Out[306]: array([False,  True, False, False,  True,  True])
In [307]: df3[~df3.index.duplicated()]
Out[307]: 
 a         b
a  0  1.440455
b  2  1.038402
c  3 -0.894409
In [308]: df3[~df3.index.duplicated(keep='last')]
Out[308]: 
 a         b
c  3 -0.894409
b  4  0.683536
a  5  3.082764
In [309]: df3[~df3.index.duplicated(keep=False)]
Out[309]: 
 a         b
c  3 -0.894409 

类似字典的get()方法

Series 或 DataFrame 的每个都有一个get方法,它可以返回默认值。

In [310]: s = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
In [311]: s.get('a')  # equivalent to s['a']
Out[311]: 1
In [312]: s.get('x', default=-1)
Out[312]: -1 

通过索引/列标签查找值

有时你想要根据一系列行标签和列标签提取一组值,这可以通过 pandas.factorize 和 NumPy 索引来实现。例如:

In [313]: df = pd.DataFrame({'col': ["A", "A", "B", "B"],
 .....:                   'A': [80, 23, np.nan, 22],
 .....:                   'B': [80, 55, 76, 67]})
 .....: 
In [314]: df
Out[314]: 
 col     A   B
0   A  80.0  80
1   A  23.0  55
2   B   NaN  76
3   B  22.0  67
In [315]: idx, cols = pd.factorize(df['col'])
In [316]: df.reindex(cols, axis=1).to_numpy()[np.arange(len(df)), idx]
Out[316]: array([80., 23., 76., 67.]) 

以前,可以使用专用的 DataFrame.lookup 方法来实现这一点,该方法在版本 1.2.0 中已弃用,并在版本 2.0.0 中删除。

Pandas 2.2 中文官方教程和指南(十一·二)(4)https://developer.aliyun.com/article/1509873

相关文章
|
1月前
|
SQL 数据采集 数据挖掘
Pandas 教程
10月更文挑战第25天
41 2
|
4月前
|
存储 JSON 数据格式
Pandas 使用教程 CSV - CSV 转 JSON
Pandas 使用教程 CSV - CSV 转 JSON
44 0
|
4月前
|
JSON 数据格式 Python
Pandas 使用教程 JSON
Pandas 使用教程 JSON
47 0
|
4月前
|
SQL 数据采集 JSON
Pandas 使用教程 Series、DataFrame
Pandas 使用教程 Series、DataFrame
77 0
|
6月前
|
数据采集 存储 数据可视化
Pandas高级教程:数据清洗、转换与分析
Pandas是Python的数据分析库,提供Series和DataFrame数据结构及数据分析工具,便于数据清洗、转换和分析。本教程涵盖Pandas在数据清洗(如缺失值、重复值和异常值处理)、转换(数据类型转换和重塑)和分析(如描述性统计、分组聚合和可视化)的应用。通过学习Pandas,用户能更高效地处理和理解数据,为数据分析任务打下基础。
797 3
|
7月前
|
存储 SQL 索引
Pandas 2.2 中文官方教程和指南(十一·二)(4)
Pandas 2.2 中文官方教程和指南(十一·二)
70 1
|
7月前
|
索引 Python
Pandas 2.2 中文官方教程和指南(十一·二)(2)
Pandas 2.2 中文官方教程和指南(十一·二)
50 1
|
7月前
|
索引 Python
Pandas 2.2 中文官方教程和指南(一)(4)
Pandas 2.2 中文官方教程和指南(一)
68 0
|
7月前
|
存储 SQL JSON
Pandas 2.2 中文官方教程和指南(一)(3)
Pandas 2.2 中文官方教程和指南(一)
109 0
|
7月前
|
XML 关系型数据库 PostgreSQL
Pandas 2.2 中文官方教程和指南(一)(2)
Pandas 2.2 中文官方教程和指南(一)
199 0

相关实验场景

更多