Pandas 2.2 中文官方教程和指南(十一·二)(2)https://developer.aliyun.com/article/1509870
query()
方法
DataFrame
对象具有一个允许使用表达式进行选择的 query()
方法。
你可以获取列b
的值在列a
和c
的值之间的帧的值。例如:
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()
语法
你也可以像操作列一样使用带有 MultiIndex
的 DataFrame
的级别:
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
in
和not in
运算符
query()
还支持 Python 的in
和not in
比较运算符的特殊用法,提供了一种简洁的语法来调用Series
或DataFrame
的isin
方法。
# 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
注意
请注意,in
和not 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()
的性能
对于大框架,使用numexpr
的DataFrame.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()
语法
您还可以像在框架中的列一样使用DataFrame
的MultiIndex
的级别:
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
in
和not in
运算符
query()
还支持对 Python 的in
和not in
比较运算符的特殊用法,提供了对Series
或DataFrame
的isin
方法的简洁语法。
# 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
没有此操作的等效操作,因此in
和not 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()
的性能
使用numexpr
的DataFrame.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 中标识并删除重复行,有两种方法可以帮助:duplicated
和drop_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