如何从路径列中获取基文件名

4

我有一个包含文件路径的DataFrame。

我想要把它改成只有文件名。

我的DataFrame看起来像:

df = pd.DataFrame({
    'Sr No': [18, 19, 20],
    'Email': ['Test@test.com', 'Test@test.com', 'Test@test.com'],
    'filename': [r'C:/Users\Test.csv', r'C:/Users\Test1.csv',
                 r'C:/Users\Test1.csv']
})
序号 电子邮件 文件名
18 Test@test.com C:/Users\Test.csv
19 Test@test.com C:/Users\Test1.csv
20 Test@test.com C:/Users\Test1.csv
  1. 文件名应该只有 Test 和 Test1
  2. 只需在 Test.csv 和 Test1.csv 中各写一次 Test@test.com。

简而言之,输出应如下:

df = pd.DataFrame({
    'Sr No': [18, 19, 20],
    'Email': ['Test@test.com', 'Test@test.com', 'Test@test.com'],
    'filename': ['Test', 'Test1', 'Test1']
})
Sr No 电子邮件地址 文件名
18 Test@test.com 测试
19 Test@test.com 测试1
20 Test@test.com 测试1

我想使用Python和Pandas DataFrame完成此操作。

'文件名'列中有100行。

我尝试过使用:

import os

import glob

myfile = os.path.basename('C:/Users/Test.csv')
os.path.splitext(myfile)
print(os.path.splitext(myfile)[0])

但它只对一个路径有用,如何将其应用于整个列?

5个回答

6
使用 pandas.Series.apply 迭代遍历列,并将结果赋值给新列。
df["filename"] = df["filename"].apply(os.path.basename)

或者

df["filename"] = df["filename"].apply(lambda path: os.path.basename(path))

例子:

>>> df
   Sr No          Email            filename
0     18  Test@test.com   C:/Users\Test.csv
1     19  Test@test.com  C:/Users\Test1.csv
2     20  Test@test.com  C:/Users\Test1.csv

>>> df["filename"] = df["filename"].apply(os.path.basename)
>>> df
   Sr No          Email   filename
0     18  Test@test.com   Test.csv
1     19  Test@test.com  Test1.csv
2     20  Test@test.com  Test1.csv

还可以使用 Path('C:/Users/Test.csv').name 选项来自 pathlib 模块,但这比 os.path.basename 更慢,因为 pathlibstring 转换为 pathlib 对象。

如果在文件名之前提供斜线,则最快的选项是使用 pandas.Series.str.split(例如:df['filename'].str.split('\\', expand=True).iloc[:, -1])。

已在 python 3.11.2pandas 2.0.0 中测试

%timeit 测试

import pandas as pd
import os
from pathlib import Path

# sample dataframe with 30000 rows
df = pd.DataFrame({'Sr No': [18, 19, 20],
                   'Email': ['Test@test.com', 'Test@test.com', 'Test@test.com'],
                   'filename': [r'C:/Users\Test.csv', r'C:/Users\Test1.csv', r'C:/Users\Test1.csv']})
df = pd.concat([df] * 10000, ignore_index=True)

# timeit tests
%timeit df["filename"].apply(lambda path: Path(path).name)
%timeit df["filename"].apply(os.path.basename)
%timeit df["filename"].apply(lambda path: os.path.basename(path))
%timeit df['filename'].str.split('\\', expand=True).iloc[:, -1]

结果

67.4 ms ± 1.72 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
43 ms ± 1.18 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
43 ms ± 1.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
15.2 ms ± 216 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

0

您需要通过重新定义现有列来进行修改。首先使用pandas读取:

import pandas as pd
df = pd.read_csv('file_path\file_name.csv')
df['filename'] = df['filename'].map(lambda x: x.split('\\')[-1][:-4])
df = df.drop_duplicates()

这将生成一个数据框作为预期结果,你所缺少的就是将其保存回csv/excel:

df.to_excel('file_path\new_file_name.xlsx')

或者 CSV:

df.to_csv('file_path\new_file_name.csv')

0
使用Pandas将Excel文件读入数据框中。
import pandas as pd
df = pd.read_excel("your excel file location")

然后使用apply函数对整个列执行一个操作,如下所示

def get_filename(path):
    temp_str = path.split('/')
    return temp_str[-1]

df["filename"] = df["filename"].apply(get_filename)

0
除了上面的答案,您还可以使用字符串方法:
df['filename'] = df['filename'].str.split('/')[-1]

不确定哪个是最快的。


然后,当你有了数据框之后,你需要检查列名是什么。它可能被称为其他名称,我们只能根据你上面提供的列名进行操作。 - GhandiFloss
这会导致 KeyError: -1 错误,因为 pandas 认为 [-1] 是一个列名,所以这不是一个有效的答案。 - Trenton McKinney

0
假设您在文件名列中有固定的目录长度:
# created dataframe for example
df = pd.DataFrame({'Email':['test@gmail.com','test@gmail.com','test@gmail.com'],
                   'filename':['c:/users\test.csv','c:/users\test1.csv','c:/users\test1.csv']} )   # dataframe

# will create new column with file name only
df['only_filename'] = [(path.encode('unicode_escape')[9:]).decode("utf-8") for path in df['filename']]
 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接