Более быстрый способ изменить значение строки в dataframe в зависимости от условия - PullRequest
0 голосов
/ 12 октября 2018

У меня есть большой фрейм данных , содержащий миллионы записей ,


data set


Списки, которые я использую в своем коде: ,

image_jpg= ['image/jpeg','image/jpg','image/pjpeg']
image_png = ['image/png','image/x-png','application/png']
image_gif = ['image/gif']

Я хочу сделать новый столбец с именемname такое, что, например:

Индекс 0 имеет content_type значение image/jpeg, которое находится в списке image_jpg, поэтому name столбец получить значение из 5efc61356f85e500694bcbbbbb3ee4c2.jpg (sys_id столбец + .jpg)


Сейчас я достигаю этого через :

file_name = []
for index, row in df.iterrows():
    if row['content_type'] in image_jpg:
        file_name.append(str(row['sys_id'])+'.jpg')
    elif row['content_type'] in image_png:
        file_name.append(str(row['sys_id'])+'.png')
    elif row['content_type'] in image_png:
        file_name.append(str(row['sys_id'])+'.gif')
    else:
        file_name.append(str(row['sys_id']))

df['name'] =  file_name

Выход :

output

Проблема в том, что это занимает довольно много времени, поскольку датафрейм довольно большой.

Есть ли более быстрый способ выполнить эту задачу?

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Я бы реструктурировал ваши списки в словарь и использовал бы карту:

df['name'] = df['id'] + df['content_type'].map(d).fillna('')

благодаря @jezrael мы также должны добавить fillna ('') для обработки ошибок.


То есть вы должны заменить свой список чем-то вроде этого:

d = {
    'application/png': '.png',
    'image/gif': '.gif',
    'image/jpeg': '.jpg',
    'image/jpg': '.jpg',
    'image/pjpeg': '.jpg',
    'image/png': '.png',
    'image/x-png': '.png',
}

Полный пример:

import pandas as pd

d = {
    'application/png': '.png',
    'image/gif': '.gif',
    'image/jpeg': '.jpg',
    'image/jpg': '.jpg',
    'image/pjpeg': '.jpg',
    'image/png': '.png',
    'image/x-png': '.png',
}

# some random data
df = pd.DataFrame({
    'id': ['1232131iujajga','21hi3hk123h21', '1231231231'],
    'content_type': ['image/gif', 'image/jpg', '']
})

df['name'] = df['id'] + df['content_type'].map(d).fillna('')
print(df)

Возвращает:

 content_type              id                name
0    image/gif  1232131iujajga  1232131iujajga.gif
1    image/jpg   21hi3hk123h21   21hi3hk123h21.jpg
2                   1231231231          1231231231
0 голосов
/ 12 октября 2018

Используйте словарь и по столбцам операции:

d = {'image_jpg': ['image/jpeg','image/jpg','image/pjpeg'],
     'image_png': ['image/png','image/x-png','application/png'],
     'image_gif': ['image/gif']}

d_rev = {w: k for k, v in d.items() for w in v}

for k, v in d_rev.items():
    mask = df['content_type'].str.contains(v, regex=False)
    df.loc[mask, 'name'] = df.loc[mask, 'sys_id'] + '.' + k.split('/')[-1]

Или, если требуется равенство:

for k, v in d_rev.items():
    mask = df['content_type'].eq(v)
    df.loc[mask, 'name'] = df.loc[mask, 'sys_id'] + '.' + k.split('/')[-1]

Для случая равенства: @ 1010 * решение * @ AntonvBR лучше.

Пояснение

d_rev отображает каждое значение списка на ключ: -

print(d_rev)

{'application/png': 'image_png', 'image/gif': 'image_gif',
 'image/jpeg': 'image_jpg', 'image/jpg': 'image_jpg',
 'image/pjpeg': 'image_jpg', 'image/png': 'image_png',
 'image/x-png': 'image_png'}

Поскольку существует очень мало категорий и большое количество строк, более эффективно перебирать словарь и использовать оптимизированные операции по столбцам.Помните, iterrows - это просто медленный цикл строк, он всегда будет неэффективным для большого количества строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...