删除 pandas DataFrame 列中字符串条目的结尾

Posted

技术标签:

【中文标题】删除 pandas DataFrame 列中字符串条目的结尾【英文标题】:Remove ends of string entries in pandas DataFrame column 【发布时间】:2016-08-28 08:38:42 【问题描述】:

我有一个 pandas 数据框,其中有一列是文件列表

import pandas as pd
df = pd.read_csv('fname.csv')

df.head()

filename    A    B    C
fn1.txt   2    4    5
fn2.txt   1    2    1
fn3.txt   ....
....

我想从filename 中的每个条目中删除文件扩展名.txt。我该如何做到这一点?

我试过了:

df['filename'] = df['filename'].map(lambda x: str(x)[:-4])

但是当我之后用df.head() 查看列条目时,什么都没有改变。

如何做到这一点?

【问题讨论】:

您的数据是'fn1.txt' 还是fn1.txt?那么你有引用字符串作为你的数据吗? @EdChum 我看不到引号 【参考方案1】:

您可以使用str.rstrip 删除结尾:

df['filename'] = df['filename'].str.rstrip('.txt')

应该工作

【讨论】:

不知道它应该有效,但问题仍然是您的数据是否有引号? 当我使用df.head() 时,我看不到引号 所以,当我尝试上面的代码时,我得到以下错误 'AttributeError: 'str' object has no attribute 'str'' 我认为rstrip 方法可能有问题,如果文件的最后一个字符包含tex。然后这个字符被删除。试试df = pd.DataFrame('A': 0: 2, 1: 1, 'C': 0: 5, 1: 1, 'B': 0: 4, 1: 2, 'filename': 0: "test.txt", 1: "x.txt", columns=['filename','A','B', 'C']) 抱歉,不是e。只有字符 tx【参考方案2】:

我认为您可以将str.replace 与正则表达式.txt$' 一起使用($ - matches the end of the string):

import pandas as pd

df = pd.DataFrame('A': 0: 2, 1: 1, 
                   'C': 0: 5, 1: 1, 
                   'B': 0: 4, 1: 2, 
                   'filename': 0: "txt.txt", 1: "x.txt", 
                columns=['filename','A','B', 'C'])

print df
  filename  A  B  C
0  txt.txt  2  4  5
1    x.txt  1  2  1

df['filename'] = df['filename'].str.replace(r'.txt$', '')
print df
  filename  A  B  C
0      txt  2  4  5
1        x  1  2  1

df['filename'] = df['filename'].map(lambda x: str(x)[:-4])
print df
  filename  A  B  C
0      txt  2  4  5
1        x  1  2  1

df['filename'] = df['filename'].str[:-4]
print df
  filename  A  B  C
0      txt  2  4  5
1        x  1  2  1

编辑:

rstrip可以删除更多的字符,如果字符串的末尾包含一些条带字符串的字符(在这种情况下.tx):

例子:

print df
  filename  A  B  C
0  txt.txt  2  4  5
1    x.txt  1  2  1

df['filename'] = df['filename'].str.rstrip('.txt')

print df
  filename  A  B  C
0           2  4  5
1           1  2  1

【讨论】:

我得到以下AttributeError: AttributeError: 'str' object has no attribute 'str' 尝试将列 filename 转换为 string - df['filename'] = df['filename'].astype(str) 即使将列转换为字符串,这些方法都不起作用 它适用于我的解决方案中的数据框? df = pd.DataFrame('A': 0: 2, 1: 1, 'C': 0: 5, 1: 1, 'B': 0: 4, 1: 2, 'filename': 0: "txt.txt", 1: "x.txt", columns=['filename','A','B', 'C']) ? 您的pandas 是什么版本? print pd.show_versions()【参考方案3】:

你可能想要:

df['filename'] = df.apply(lambda x: x['filename'][:-4], axis = 1)

【讨论】:

如果不是固定大小的 -4 你我需要更灵活的说法,去掉逗号或句点之后的最后一个词,怎么样?【参考方案4】:

使用列表理解

df['filename'] = [x[:-4] for x in df['filename']]

【讨论】:

如果最后一个或第一个字符是“X”,我想删除最后一个或第一个字符。请举例【参考方案5】:

2021 年更新 + 速度测试

从pandas 1.4开始,相当于str.removesuffix,实现了pandas.Series.str.removesuffix,所以可以使用

df['filename'].str.removesuffix('.txt')

速度测试

tl;dr: 最快的是

dat["fname"].map(lambda x: x[:-4] if x[-4:] == ".txt" else x)

在速度测试中,我想考虑这个 SO 页面中收集的不同方法。我排除了rstrip,因为它也会去除.txt以外的结尾,并且由于正则表达式包含条件,因此修改其他函数也是公平的,以便它们仅在它们是.txt时删除最后4个字符.

测试代码是

import pandas as pd
import time

ITER = 10


def rm_re(dat: pd.DataFrame) -> pd.Series:
    """Use regular expression."""
    return dat["fname"].str.replace(r'.txt$', '', regex=True)


def rm_map(dat: pd.DataFrame) -> pd.Series:
    """Use pandas map, find occurrences and remove with []"""
    where = dat["fname"].str.endswith(".txt")
    dat.loc[where, "fname"] = dat["fname"].map(lambda x: x[:-4])
    return dat["fname"]


def rm_map2(dat: pd.DataFrame) -> pd.Series:
    """Use pandas map with lambda conditional."""
    return dat["fname"].map(lambda x: x[:-4] if x[-4:] == ".txt" else x)


def rm_apply_str_suffix(dat: pd.DataFrame) -> pd.Series:
    """Use str method suffix with pandas apply"""
    return dat["fname"].apply(str.removesuffix, args=(".txt",))


def rm_suffix(dat: pd.DataFrame) -> pd.Series:
    """Use pandas removesuffix from version 1.6"""
    return dat["fname"].str.removesuffix(".txt")


functions = [rm_map2, rm_apply_str_suffix, rm_map, rm_suffix, rm_re]
for base in range(12, 23):
    size = 2**base
    data = pd.DataFrame("fname": ["fn"+str(i) for i in range(size)])
    data.update(data.sample(frac=.5)["fname"]+".txt")
    for func in functions:
        diff = 0
        for _ in range(ITER):
            data_copy = data.copy()
            start = time.process_time()
            func(data_copy)
            diff += time.process_time() - start

        print(diff, end="\t")

输出如下图:

从图中可以看出,最慢的解是正则表达式,最快的是带条件的pandas.Series.map。在更高版本的 pandas 中,这可能会改变,我预计 pandas.Series.str.removesuffix 会有所改进,因为它在矢量化方面具有更大的潜力。

必须从 2021 年 11 月 30 日起从源代码安装 Pandas,因为 1.4 版仅处于开发阶段。我按照pandas dev repo 的说明安装它,克隆项目并使用python setup.py install 安装。

我的机器:

AMD 锐龙 5 2400G 带 Radeon Vega 显卡,3.60 GHz Windows 10 20H2 Python 3.10.0,pandas.版本 '1.4.0.dev0+1267.gaee662a7e3',numpy.版本 '1.21.4'

【讨论】:

以上是关于删除 pandas DataFrame 列中字符串条目的结尾的主要内容,如果未能解决你的问题,请参考以下文章

从 Pandas DataFrame 列中删除特定符号(unicode)[重复]

删除pandas dataframe index中的字符范围

pandas使用duplicated函数删除dataframe中重复列名称的数据列默认保留重复数据列中的第一个数据列(removing duplicate columns in dataframe)

如何从列类型列表中删除 pandas DataFrame 中的空值

从 Pandas Dataframe Column 中删除重复的逗号,换句话说,我只需要列中的文本,用逗号分隔它们

Pandas Dataframe - 如何检查列中数值的符号,如果为负则删除符号并在发生这种情况时创建另一列?