删除未由 Pandas 中的索引唯一标识的行
Deleting rows not uniquely identified by the index in Pandas
如何从 Pandas DataFrame 中删除(删除)行,其中的行 不是 由索引唯一标识的?
澄清我所说的唯一标识的意思:查询索引时,返回多个值。
我可以制作一个掩码,当它用作 df.loc
的参数时,可以正确地 returns 目标行,但我不能让它与 df.drop
一起使用。
示例代码:
打印函数的输出包含在注释中。
from __future__ import print_function
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(
data=np.random.randint(0, 10, size=(7, 3)),
index=[['u01', 'u01', 'u01', 'u02', 'u02', 'u03', 'u03'], ['C', 'C', 'C', 'C', 'T', 'T', 'T']],
columns=['foo', 'bar', 'baz'])
df.index.names = ['user', 'comType']
print(df)
# foo bar baz
# user comType
# u01 C 5 0 3
# C 3 7 9
# C 3 5 2
# u02 C 4 7 6
# T 8 8 1
# u03 T 6 7 7
# T 8 1 5
mask = (df.baz > 8) | (df.baz < 2)
print(mask)
# user comType
# u01 C False
# C True
# C False
# u02 C False
# T True
# u03 T False
# T False
# Name: baz, dtype: bool
print(df.loc[mask])
# foo bar baz
# user comType
# u01 C 3 7 9
# u02 T 8 8 1
df2 = df.drop(mask.index[mask.values]) # Drops all rows of user user u01, one row of user u02
print(df2)
# foo bar baz
# user comType
# u02 C 4 7 6
# u03 T 6 7 7
# T 8 1 5
df3 = df.drop(mask) # Doesn't do anything
print(df3)
# foo bar baz
# user comType
# u01 C 5 0 3
# C 3 7 9
# C 3 5 2
# u02 C 4 7 6
# T 8 8 1
# u03 T 6 7 7
# T 8 1 5
一个小提示:如果你想运行你自己机器上的代码,我建议用这些行替换打印函数,否则输出很难辨别形式彼此:
print('df', df, sep=" =\n\n", end="\n"*5)
print('mask', mask, sep=" =\n\n", end="\n"*5)
print('df.loc[mask]', df.loc[mask], sep=" =\n\n", end="\n"*5)
print('df2', df2, sep=" =\n\n", end="\n"*5)
print('df3', df3, sep=" =\n\n", end="\n"*5)
因为您已经有了一个布尔掩码,所以您可以只使用它而不是通过使用一元非 ~
:
进行反转来删除
In [199]:
mask
Out[199]:
u01 C False
C True
C False
u02 C True
T False
u03 T True
T False
Name: baz, dtype: bool
In [198]:
df[~mask]
Out[198]:
foo bar baz
u01 C 0 5 8
C 5 2 7
u02 T 6 7 3
u03 T 6 5 5
drop
获取用于删除的标签值,您传递的是一个完整的布尔掩码,因此没有任何内容被删除,因为所有标签都存在,除了您想要的是索引值,但即使那样它也不会起作用:
In [212]:
df.drop(mask[~mask].index)
Out[212]:
foo bar baz
u02 C 3 7 1
因为您的多索引标签在第一层重复,因此您最终只有一行,掩码就是您所需要的
通过 ~
和 boolean indexing
:
使用反转布尔掩码
mask = (df.baz > 8) | (df.baz < 2)
print (mask)
user comType
u01 C False
C True
C False
u02 C False
T True
u03 T False
T False
Name: baz, dtype: bool
print(~mask)
user comType
u01 C True
C False
C True
u02 C True
T False
u03 T True
T True
Name: baz, dtype: bool
print (df[~mask])
foo bar baz
user comType
u01 C 5 0 3
C 3 5 2
u02 C 4 7 6
u03 T 6 7 7
T 8 1 5
如何从 Pandas DataFrame 中删除(删除)行,其中的行 不是 由索引唯一标识的?
澄清我所说的唯一标识的意思:查询索引时,返回多个值。
我可以制作一个掩码,当它用作 df.loc
的参数时,可以正确地 returns 目标行,但我不能让它与 df.drop
一起使用。
示例代码:
打印函数的输出包含在注释中。
from __future__ import print_function
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(
data=np.random.randint(0, 10, size=(7, 3)),
index=[['u01', 'u01', 'u01', 'u02', 'u02', 'u03', 'u03'], ['C', 'C', 'C', 'C', 'T', 'T', 'T']],
columns=['foo', 'bar', 'baz'])
df.index.names = ['user', 'comType']
print(df)
# foo bar baz
# user comType
# u01 C 5 0 3
# C 3 7 9
# C 3 5 2
# u02 C 4 7 6
# T 8 8 1
# u03 T 6 7 7
# T 8 1 5
mask = (df.baz > 8) | (df.baz < 2)
print(mask)
# user comType
# u01 C False
# C True
# C False
# u02 C False
# T True
# u03 T False
# T False
# Name: baz, dtype: bool
print(df.loc[mask])
# foo bar baz
# user comType
# u01 C 3 7 9
# u02 T 8 8 1
df2 = df.drop(mask.index[mask.values]) # Drops all rows of user user u01, one row of user u02
print(df2)
# foo bar baz
# user comType
# u02 C 4 7 6
# u03 T 6 7 7
# T 8 1 5
df3 = df.drop(mask) # Doesn't do anything
print(df3)
# foo bar baz
# user comType
# u01 C 5 0 3
# C 3 7 9
# C 3 5 2
# u02 C 4 7 6
# T 8 8 1
# u03 T 6 7 7
# T 8 1 5
一个小提示:如果你想运行你自己机器上的代码,我建议用这些行替换打印函数,否则输出很难辨别形式彼此:
print('df', df, sep=" =\n\n", end="\n"*5)
print('mask', mask, sep=" =\n\n", end="\n"*5)
print('df.loc[mask]', df.loc[mask], sep=" =\n\n", end="\n"*5)
print('df2', df2, sep=" =\n\n", end="\n"*5)
print('df3', df3, sep=" =\n\n", end="\n"*5)
因为您已经有了一个布尔掩码,所以您可以只使用它而不是通过使用一元非 ~
:
In [199]:
mask
Out[199]:
u01 C False
C True
C False
u02 C True
T False
u03 T True
T False
Name: baz, dtype: bool
In [198]:
df[~mask]
Out[198]:
foo bar baz
u01 C 0 5 8
C 5 2 7
u02 T 6 7 3
u03 T 6 5 5
drop
获取用于删除的标签值,您传递的是一个完整的布尔掩码,因此没有任何内容被删除,因为所有标签都存在,除了您想要的是索引值,但即使那样它也不会起作用:
In [212]:
df.drop(mask[~mask].index)
Out[212]:
foo bar baz
u02 C 3 7 1
因为您的多索引标签在第一层重复,因此您最终只有一行,掩码就是您所需要的
通过 ~
和 boolean indexing
:
mask = (df.baz > 8) | (df.baz < 2)
print (mask)
user comType
u01 C False
C True
C False
u02 C False
T True
u03 T False
T False
Name: baz, dtype: bool
print(~mask)
user comType
u01 C True
C False
C True
u02 C True
T False
u03 T True
T True
Name: baz, dtype: bool
print (df[~mask])
foo bar baz
user comType
u01 C 5 0 3
C 3 5 2
u02 C 4 7 6
u03 T 6 7 7
T 8 1 5