Python 从长度不等的字符串创建数据帧

Python 从长度不等的字符串创建数据帧,python,pandas,numpy,dataframe,Python,Pandas,Numpy,Dataframe,我有一个连续字符串格式的文件名及其路径的数据框: e、 g: 框架的大小约为1.02E+06个条目,驱动器的深度最多为21个文件夹,但差异很大。 目标是拥有以下格式的数据帧: name level1 level2 level3 level4 ... level21 0 file.txt folder1 folder2 folder3 0 ... 0 1 file.pdf

我有一个连续字符串格式的文件名及其路径的数据框:

e、 g:

框架的大小约为1.02E+06个条目,驱动器的深度最多为21个文件夹,但差异很大。 目标是拥有以下格式的数据帧:

     name           level1     level2     level3    level4  ...  level21
0    file.txt       folder1    folder2    folder3      0    ...    0      
1    file.pdf       folder1       0          0         0    ...    0   
2    file3.xls      folder1    folder2    folder3   folder4 ...  folder21
...
我拆分了文件位置的字符串并创建了一个数组,如果路径较短,可以用零填充:

files = files.assign(plist=files['path'].iloc[:].apply(path_split))

def path_split(name):
     return np.array(os.path.normpath(name).split(os.sep)[7:])
在文件路径中添加包含文件夹编号的列:

files = files.assign(len_plist = files.plist.iloc[:].map(len))
这里的问题是分割路径字符串在数据帧中创建了嵌套数组。 然后是一个空数据框,其中列数为文件夹数(此处为21),行数为文件数(此处为1.02E+06):

现在我用path数组的条目填充空框:

levels = fill_rows(levels,files.plist.values)   

def fill_rows(df,array):
    for i,row in enumerate(array):
        df.iloc[i,:row.shape[0] - 1] = row[:-1]
    return df
这需要很多时间,因为路径数组的长度不同,不允许立即使用矢量化解决方案。如果我需要循环数据帧的所有1.02E+06行,至少需要34小时,可能最多需要200小时

首先也是最重要的,我想优化数据帧的填充,在第二步中,我将拆分数据帧,并行化操作,然后再次组装数据帧


编辑:增加了澄清,短路径可以用零填充到最大长度。

也许我遗漏了一些东西,但为什么这对您不起作用

expanded = files['path'].str.split(os.path.sep, expand=True).fillna(0)
expanded = expanded.rename(columns=lambda x: 'level_' + str(x))
df = pd.concat([files.name, expanded], axis=1)

你能知道路径的最大深度吗?你说的21,把产生的例子代码只有7。。。是否可以选择最初为该最大值创建所有列,并使用
path\u split
始终返回该最大值的数组?更新问题以澄清文件夹的最大数量实际上是21,如果路径较短,则条目仍为“0”。非常感谢您的帮助。扩展功能选项是缺少的一部分。只需稍作微调:文件名itsseld始终位于最后一级列中,而不是文件所在的最后一个文件夹中。我能把每行的最后一列删掉,跳过前面中间的几行吗?对不起,我不知道你的意思。对我来说,
df
似乎具有您描述的目标格式。file1.txt数据框的第一行看起来如下:[file.txt,folder1,folder2,folder3,file.txt,0,0,0,…,0]。因为在路径的末尾,文件本身被写入。我想分离文件名,只保留路径。我想知道是否可以在这里使用,或者我需要在提交之前使用它。您应该首先使用
文件['path']拆分文件名。str.rsplit(os.path.sep,n=1,expand=True)
levels = fill_rows(levels,files.plist.values)   

def fill_rows(df,array):
    for i,row in enumerate(array):
        df.iloc[i,:row.shape[0] - 1] = row[:-1]
    return df
expanded = files['path'].str.split(os.path.sep, expand=True).fillna(0)
expanded = expanded.rename(columns=lambda x: 'level_' + str(x))
df = pd.concat([files.name, expanded], axis=1)