如何从路径字符串的DataFrame列中提取基本路径

10 投票
4 回答
7322 浏览
提问于 2025-04-18 17:31

关于字符串处理的问题有很多,但我找不到一个能让我做到以下事情的答案——我觉得这应该很简单...

我有一个数据表(DataFrame),里面有一列是文件名和路径。

下面的代码展示了一个代表性的示例数据表:

df = pd.DataFrame({
    'root': {'1': 'C:\\folder1\\folder2\\folder3\\folder4\\filename.csv'}
})
                                              root
1  C:\folder1\folder2\folder3\folder4\filename.csv

我想要的只是字符串中的'文件名'部分。因为有很多行数据,而且路径不固定,所以我不能使用 str.replace

我可以这样去掉右边的 '.csv' 部分:

df['root'] = df['root'].str.rstrip('.csv') 
                                          root
1  C:\folder1\folder2\folder3\folder4\filename

但是我试过的各种方法都无法去掉字符串左边的路径部分。

考虑到路径的前面部分可能会因记录而异,我该如何只提取出这个路径中的'文件名'部分呢?

4 个回答

1

这和pandas没有任何关系,这只是基本的路径处理,使用的是os.path模块。

其次,Windows/DOS系统至少在过去10到15年里就已经可以接受/作为路径分隔符了。所以你可以并且应该这样写:mypath = 'C:/folder1/folder2/folder3/folder4/filename.csv'。正如你所注意到的,使用反斜杠会让你的字符串处理变得麻烦,因为它需要转义,这样代码就会变得更复杂。定义os.sep = r'\\'似乎也不起作用。

import os
os.path.basename(r'C:/folder1/folder2/folder3/folder4/filename.csv')
'filename.csv'

现在,如果你真的想在你的Python代码中坚持使用特定于操作系统的代码(虽然完全没有必要这样做),你可以使用os.path的一些不太为人知的特定平台版本:

import ntpath  # Windows/DOS-specific versions of os.path
ntpath.basename(r'C:\folder1\folder2\folder3\folder4\filename.csv')
'filename.csv'
2

假设路径中总是至少有一层深度,我们可以通过斜杠来分割这个路径,取最后一个元素,然后对它使用rstrip方法去掉末尾的空格。

In [9]:

df.root.str.split('\\').str[-1].str.rstrip('.csv')
Out[9]:
1    filename
Name: root, dtype: object

编辑:根据DSM提到的关于rstrip的内容,你可以调用split两次来处理。

In [11]:

df.root.str.split('\\').str[-1].str.split('.').str[0]
Out[11]:
1    filename
Name: root, dtype: object
3

对于最近的Python版本,推荐使用pathlib这个库。你可以通过使用.stem来获取文件的基本名称。一般来说,数据表(DataFrame)通常有多行数据,所以下面的例子也使用了pandas的.apply方法。

from pathlib import Path 

df['root'].apply(lambda x: Path(x).stem)
# Out[1]:
# 1    filename
# Name: root, dtype: object

如果你想要包含文件的扩展名,可以通过使用.name来获取。

df['root'].apply(lambda x: Path(x).name)
# Out[2]:
# 1    filename.csv
# Name: root, dtype: object
12

你可以使用os.path里的工具来简化这个过程,特别是splitextbasename这两个函数:

>>> import os
>>> df["root"].apply(lambda x: os.path.splitext(os.path.basename(x))[0])
0    filename
Name: root, dtype: object

另外,rstrip的工作方式可能和你想的不一样——它是用来去掉那些字符,而不是去掉某个子字符串。举个例子:

>>> "a11_vsc.csv".rstrip(".csv")
'a11_'

撰写回答