【问题标题】:How to append all files in directory using column from CSV?如何使用 CSV 中的列附加目录中的所有文件?
【发布时间】:2017-10-15 14:10:07
【问题描述】:

我有一个包含 10,000 张图像的目录。它们被标记为 1.png、2.png 等。我有一个 CSV 文件,其中包含 10,000 个标签,如青蛙、卡车等。如何循环遍历所有文件以从 CSV 添加标签? 1.png 变为 'frog.1.png' 假设青蛙是 csv 中的标签 1。

这是我迄今为止尝试过的:

import os, sys, fileinput
import pandas as pd
#read csv labels
labels = pd.read_csv('trainLabels.csv',sep=',',header=0,usecols=[1])

#sort files in directory numerically
fnames = sorted([fname for fname in os.listdir(data_dir) 
if fname.endswith('.png')], key=lambda f: int(f.rsplit(os.path.extsep, 1)
[0].rsplit(None,1)[-1]))

#Now that order of labels and files match, rename all files using common counter, i
i = 0
for fname in os.listdir(data_dir):
     os.rename(fnames[i],labels[i]+'.'+fnames[i])
     i = i+1

os.rename 不适用于系列,我无法找到适应不同数据类型的约定。

【问题讨论】:

  • "os.rename 不适用于系列"。不知道这意味着什么。
  • 对不起,我得到的错误类型是:TypeError: 'NoneType' object is not subscriptable
  • None 是哪个值?

标签: python loops csv directory


【解决方案1】:

从外观上看,您的标签变量是不可下标的,这意味着您不能按照您的方式调用其中一个元素。

来自熊猫文档:

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html

pd.read_csv 返回 DataFrame 或 TextParser,而不是我认为您期望的行列表

您不需要“需要”熊猫来阅读该 csv:

labels = open('trainLabels.csv','r').read().split('\n')

[labels[i]=labels[i].split(',')[0] for i in range(len(labels))] 
#increment 0 above to whatever the column index you want is, this will return the first column

print(labels) #just to check it looks the way you want it to 

确定这是一个额外的行,不那么可读,但你得到了你想要的数据结构

【讨论】:

    【解决方案2】:

    为演示做了一些准备:

    $ for f in `echo "1 2 3 4 10"`; do touch "${f}.png"; done
    $ echo "a,b,c,d,e" > names.csv
    $ ls
    1.png      2.png      3.png      4.png      10.png      names.csv
    

    我有 1,2,3,4,10(而不是 5)来演示排序而不是创建 10 个文件。它适用于任意数量的文件。

    在 Python 中,在同一个目录中运行:

    >>> import os
    >>> import csv
    >>> with open('names.csv', 'r') as file:
    ...     reader = csv.reader(file)  
    ...     labels = reader.next()  # reader is a regular iterator, you can also iterate row by row.
    >>> labels
    ['a', 'b', 'c', 'd', 'e']
    >>> fnames = [fname for fname in os.listdir('.') if fname.endswith('.png')]
    ['1.png', '10.png', '2.png', '3.png', '4.png']  # Because string '10.png' comes earlier than '2.png'
    >>> fnames = sorted(fnames, key = lambda f: int(os.path.splitext(f)[0]))  # If fnames contain full paths you will need to modify this
    >>> fnames
    ['1.png', '2.png', '3.png', '4.png', '10.png']  # Now we have correct numerical order
    >>> len(labels) == len(fnames)  # For consistency should check this. Depends on your requirements.
    True
    >>> for label, fname in zip(labels, fnames):
    ...     os.rename(fname, label + '_' + fname)
    

    结果:

    $ ls
    a_1.png    b_2.png    c_3.png    d_4.png    e_10.png   names.csv
    

    注意事项:

    • 如果您使用不同的 csv 阅读器,只需确保您的 labels 变量包含您想要的名称,而不是某些对象或迭代器。我使用了 Python standard library 的 csv 阅读器。
    • 如果您有更复杂的文件名结构(不是<number>.png),您的工作将变得更加艰难,并且需要更多代码进行排序。如果你想让它更容易,只需用前导零填充所有数字,例如对于10000 文件,文件名将是00001.png00002.png 等等。操作系统会自动为您排序。

    【讨论】:

      猜你喜欢
      • 2021-06-16
      • 2021-07-05
      • 1970-01-01
      • 1970-01-01
      • 2015-10-22
      • 2018-06-25
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多