Есть ли более эффективный инструмент, чем iterrows () в этой ситуации? - PullRequest
0 голосов
/ 28 июня 2018

Хорошо, вот в чем дело. Я работаю с большим количеством фреймов данных и массивов панд. Часто мне нужно соединить значение из одного кадра со значением из другого, в идеале в конечном итоге объединить информацию в один кадр.

Скажем, я смотрю на файлы изображений. Там есть набор информации, специфичной для каждого файла. Иногда есть определенные типы графических файлов, которые совместно используют одну и ту же информацию. Простой пример:

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 строк в каждом кадре занимает FOREVER .:

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 голосов
/ 28 июня 2018

Если вы можете разделить имя файла от 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.

0 голосов
/ 28 июня 2018

сосредоточив внимание на второй половине вашего вопроса, поскольку именно для этого вы предоставили код. Ваша программа проверяет каждую строку df1 по каждой строке в df2, потенциально получая 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), разделяем путь на \, чтобы извлечь файл, а затем создаем словарь файлов для номеров строк , Далее мы инициализируем 3 столбца в оригинальном DataFrame, в который вы хотите записать.

Наконец, мы перебираем файлы в originalDataframe, проверяем, существует ли этот файл в нашем словаре файлов в otherDataframe (сделано в попытке отловить ошибки), и извлекаем номер строки (из словаря), который мы затем используйте для записи значений из другого в исходное.

Дополнительное замечание: вы описываете пути, которые находятся в ключе 'C: /asd/fdg/img2.jpg', и в этом случае вы должны использовать:

*_, file = path.split('/')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...