在这种情况下,有没有比iterrows()更有效的工具?

时间:2018-06-28 15:06:50

标签: python performance pandas dataframe

好吧,这就是事情。我正在处理许多熊猫数据框和数组。通常,我需要将一帧中的值与另一帧中的值配对,理想情况下最后将信息组合成一帧。

说我正在查看图像文件。每个文件都有一组特定的信息。有时,某些类型的图像文件共享相同类型的信息。简单的例子:

FILEPATH,    TYPE,   COLOR,   VALUE_I,<br>
/img2.jpg,    A,    'green',   0.6294<br>
/img45.jpg,   B,    'green',   0.1846<br>
/img87.jpg,   A,    'blue',    34.78<br>

通常,此信息通过类型/颜色/值等索引出来,并馈入其他函数,这给了我另一个重要的输出,例如VALUE_II。但是我不能将其直接连接到原始数据帧上,因为由于输出的性质或因为我只喂入了框架的一部分,所以索引不匹配。

或者另一种情况:我了解到某种类型的图像具有附加的特定值,因此我制作了一个类型及其值的字典。同样,此列不存在,因此在这种情况下,我将使用iterrows()推进框架,查看类型是否与特定键匹配,以及是否将其附加到数组中。然后最后,我将该数组转换为一个数据框,并将其连接到原始数组上。

这是罪魁祸首。每帧最多包含1800行,因此需要永远执行。:

newColumn = []

for index, row in originalDataframe.iterrows():
    for indx, rw in otherDataframe.iterrows():
        if row['filename'] in rw['filepath']:
            newColumn.append([rw['VALUE_I'],rw['VALUE_II'], rw['VALUE_III']])

newColumn = pd.DataFrame(newColumn, columns = ['VALUE_I', 'VALUE_II', 'VALUE_III'])
originalDataframe = pd.concat([originalDataframe, newColumn], axis=1)

解决方案将不胜感激!

2 个答案:

答案 0 :(得分:1)

如果可以从otherDataframe["filepath"]中拆分文件名,则可以只与orinalDataframe的文件名进行比较,而无需检查in。之后,您可以使用pandas.DataFrame.join简化计算,对于originalDataframe中的每个文件名,它将在otherDataframe中找到相同的文件名,并从中添加所有其他列。

import os

otherDataframe["filename"] = otherDataframe["filepath"].map(os.path.basename)
joinedDataframe = originalDataframe.join(otherDataframe.set_index("filename"), on="filename")

如果originalDataframe和otherDataframe中存在具有相同名称的列,则应设置lsuffix或rsuffix。

答案 1 :(得分:0)

关注问题的后半部分,因为这是您提供的代码。您的程序正在对照df2中的每一行检查df1的每一行,可能产生1800 * 1800或3240000个可能的组合。如果每一行只有一个可能的匹配项,则添加“ break”会有所帮助,但这并不理想。 newColumn.append([rw['VALUE_I'],rw['VALUE_II'], rw['VALUE_III']]) break

如果您的数据结构允许,我会尝试类似的操作

ref = {}
for i, path in enumerate(otherDataframe['filepath']):
   *_, file = path.split('\\')
   ref[file] = i

originalDataframe['VALUE_I'] = None
originalDataframe['VALUE_II'] = None
originalDataframe['VALUE_III'] = None

for i, file in enumerate(originalDataframe['filename']):
    try:
        j = ref[file]
        originalDataframe.loc[i, 'VALUE_I'] = otherDataframe.loc[j, 'VALUE_I']
        originalDataframe.loc[i, 'VALUE_II'] = otherDataframe.loc[j, 'VALUE_II']
        originalDataframe.loc[i, 'VALUE_III'] = otherDataframe.loc[j, 'VALUE_III']
    except:
        pass

在这里,我们遍历otherDataframe中的路径(我假设它们遵循C:\ asdf \ asdf \ file的模式),在\上分割路径以提取文件,然后构造一个文件字典至行号。接下来,我们初始化要写入的originalDataframe中的3列。

最后,我们遍历originalDataframe中的文件,检查该文件是否存在于otherDataframe中的文件字典中(尝试捕获错误),然后从中取出行号(从字典中取出)用于将其他值写入原始值。

旁注,您将路径描述为“ C:/asd/fdg/img2.jpg”的脉络,在这种情况下,应使用:

*_, file = path.split('/')