删除Pandas中索引未唯一标识的行

时间:2016-12-21 13:41:37

标签: python pandas indexing multi-index

如何从Pandas DataFrame中删除(删除)行,其中行由索引唯一标识?
通过唯一标识来阐明我的意思:查询索引时,会返回多个值。

我可以创建一个掩码,当用作df.loc的参数时,正确返回目标行,但我无法使其与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-functions,因为输出很难彼此辨别:

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)

2 个答案:

答案 0 :(得分:1)

由于你已经有了一个布尔掩码,你可以使用它而不是通过使用一元而不是~来反转:

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获取drop的标签值,你传递的是一个完整的布尔掩码,所以没有任何东西被删除,因为所有标签都存在,除了你想要的是索引值,但即便如此它也不会有效: / p>

In [212]:
df.drop(mask[~mask].index)

Out[212]:
       foo  bar  baz
u02 C    3    7    1

因为您的多索引标签在第一级被重复,因此为什么你最终得到一行,掩码就是你需要的所有

答案 1 :(得分:1)

使用string regout = @"abc\n\def\n\ghi\n\\".Replace(@"\n\", ""); ~的反转布尔值掩码:

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