首页 > 解决方案 > 如果列与特定字符串匹配,则删除数据框中的行

问题描述

我试图遵循这里提到的过程,但它对我来说不起作用(完全),所以请指出我可能丢失的任何重复项,所以下面是 我在尝试过滤的地方被阻止的要求在将数据插入 Postgres 之前具有以下条件的数据。

名字和姓氏列不应包含 [Jr, Sr, I, II, etc]。或删除整个记录/行

columns = [
        'cust_last_nm',
        'cust_frst_nm',
        'cust_brth_dt',
        'cust_gendr_cd',
        'cust_postl_cd'
    ]
def push_to_pg_weekly(key):
    total_rows = int(a.split()[0])
    rows = 0
    for chunk in pd.read_csv(key, sep="|", header=None, chunksize=100000):
        rows += len(chunk)
        chunk = chunk.dropna(axis=0)
        chunk = chunk[np.where(
         (chunk[0].astype('str').str.len()>1) & 
         (chunk[1].astype('str').str.len()>1) &
         (chunk[4].astype('str').str.len()>4) &
         (chunk[4].astype('str').str.len()<8), True, False)]
        chunk[0] = ~chunk[0].str.contains("jr", na=False)
        chunk[1] = ~chunk[1].str.contains("jr", na=False)
        chunk.to_csv("/tmp/sample.csv", sep="|", header=None, index=False)
        connection = psycopg2.connect(connection details <here>)
        with connection.cursor() as cursor:
            connection.commit()

我正在处理的测试数据

jane|doe|1969-01-01|F|926.0|1351127|E2sboFz4Mk2aGIKhD4vm6J9Jt3ZSoSdLm+0PCdWsJto=|YSILMFS5sPPZZF/KFroEHV77z1bMeiL/f4FqF2kj4Xc=|tNjgnby5zDbfT2SLsCCwhNBxobSDcCp7ws0zYVme5w4=|kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=|cigna_TOKEN_ENCRYPTION_KEY
jr|doe|1969-01-01|M|926.0|1351127|E2sboFz4Mk2aGIKhD4vm6J9Jt3ZSoSdLm+0PCdWsJto=|YSILMFS5sPPZZF/KFroEHV77z1bMeiL/f4FqF2kj4Xc=|tNjgnby5zDbfT2SLsCCwhNBxobSDcCp7ws0zYVme5w4=|kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=|cigna_TOKEN_ENCRYPTION_KEY
jane|sr|1969-01-01|F|926.0|1351127|E2sboFz4Mk2aGIKhD4vm6J9Jt3ZSoSdLm+0PCdWsJto=|YSILMFS5sPPZZF/KFroEHV77z1bMeiL/f4FqF2kj4Xc=|tNjgnby5zDbfT2SLsCCwhNBxobSDcCp7ws0zYVme5w4=|kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=|cigna_TOKEN_ENCRYPTION_KEY

我知道我的方向是正确的,但仍然缺少其他东西,因为当我尝试这个时

chunk[0] = ~chunk[0].str.contains("jr", na=False)

我得到以下输出:而不是 False 我期望删除整行

True|True|1969-01-01|F|926.0|1351127|E2sboFz4Mk2aGIKhD4vm6J9Jt3ZSoSdLm+0PCdWsJto=|YSILMFS5sPPZZF/KFroEHV77z1bMeiL/f4FqF2kj4Xc=|tNjgnby5zDbfT2SLsCCwhNBxobSDcCp7ws0zYVme5w4=|kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=|cigna_TOKEN_ENCRYPTION_KEY
False|True|1969-01-01|M|926.0|1351127|E2sboFz4Mk2aGIKhD4vm6J9Jt3ZSoSdLm+0PCdWsJto=|YSILMFS5sPPZZF/KFroEHV77z1bMeiL/f4FqF2kj4Xc=|tNjgnby5zDbfT2SLsCCwhNBxobSDcCp7ws0zYVme5w4=|kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=|cigna_TOKEN_ENCRYPTION_KEY
True|True|1969-01-01|F|926.0|1351127|E2sboFz4Mk2aGIKhD4vm6J9Jt3ZSoSdLm+0PCdWsJto=|YSILMFS5sPPZZF/KFroEHV77z1bMeiL/f4FqF2kj4Xc=|tNjgnby5zDbfT2SLsCCwhNBxobSDcCp7ws0zYVme5w4=|kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=|cigna_TOKEN_ENCRYPTION_KEY

预期输出:

jane|doe|1969-01-01|F|926.0|1351127|E2sboFz4Mk2aGIKhD4vm6J9Jt3ZSoSdLm+0PCdWsJto=|YSILMFS5sPPZZF/KFroEHV77z1bMeiL/f4FqF2kj4Xc=|tNjgnby5zDbfT2SLsCCwhNBxobSDcCp7ws0zYVme5w4=|kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=|cigna_TOKEN_ENCRYPTION_KEY

我的另一个问题是:我可以尝试在 str.contains 中包含多个参数来过滤更多条件吗?我尝试了以下两种方法,但没有奏效,它们都产生了真/假结果

chunk[0] = ~chunk[0].str.contains("jr", “sr”, “|”, “||”, na=False)
chunk[1] = ~chunk[1].str.contains("jr", “sr”, “|”, “||”,  na=False)
or
searchfor = [‘jr’, ’sr’,’|’,’||’]
chunk[0] = ~chunk.chunk[0].str.contains('|'.join(searchfor))]
chunk[1] = ~chunk.chunk[1].str.contains('|'.join(searchfor))]

或者我应该使用 drop 方法来删​​除行,任何建议或意见将不胜感激,谢谢

标签: pythonpandasdataframe

解决方案


本质上,您忘记将布尔系列(真/假)传递到括号[...]中,或者更好地使用.loc[...]. 相反,您将这些块列中的值重新分配给条件的结果,但没有将条件逻辑地应用于数据框。

因此,考虑调用.loc[]这两个条件的交集:

# ASSIGN BOOLEAN SERIES
fname_jr = ~chunk.loc[0].str.contains("jr", na=False)
lname_jr = ~chunk.loc[1].str.contains("jr", na=False)

# PASS INTO .loc
chunk_sub = chunk.loc[fname_jr & lname_jr]
chunk_sub

#       0    1   ...                                            9                          10
# 0  jane  doe  ...  kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=  cigna_TOKEN_ENCRYPTION_KEY
# 2  jane   sr  ...  kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=  cigna_TOKEN_ENCRYPTION_KEY

要集成多个选择,请调用str.join以将项目列表与管道分隔符组合:

# ASSIGN BOOLEAN SERIES
fname_jr_sr = ~chunk[0].str.contains("|".join(["sr", "jr"]), na=False)
lname_jr_sr = ~chunk[1].str.contains("|".join(["sr", "jr"]), na=False)

# PASS INTO .loc
chunk_sub = chunk.loc[fname_jr_sr & lname_jr_sr]
chunk_sub
#       0    1   ...                                            9                          10
# 0  jane  doe  ...  kk25p0lrp2T54Z3B1HM3ZQN0RM63rjqvewrwW5VhYcI=  cigna_TOKEN_ENCRYPTION_KEY

相关地,您的np.where调用不是必需的,因为.loc它将在布尔系列上运行。由于管道符号是字符串匹配运算符,因此请务必|使用反斜杠进行转义。\\共:

chunk = chunk.loc[(chunk[0].astype('str').str.len()>1) & 
                  (chunk[1].astype('str').str.len()>1) &
                  (chunk[4].astype('str').str.len()>4) &
                  (chunk[4].astype('str').str.len()<8) & 
                  ~chunk[0].str.contains("|".join(["sr", "jr", "\\|", "\\|\\|"]), na=False) & 
                  ~chunk[1].str.contains("|".join(["sr", "jr", "\\|", "\\|\\|"]), na=False)]

chunk.to_csv("/tmp/sample.csv", sep="|", header=None, index=False)

推荐阅读