#python #pandas #dataframe
Вопрос:
Мне нужно повторить кадр данных, для каждой строки мне нужно создать идентификатор на основе двух существующих столбцов: имя и пол. В конце концов я добавляю эту новую колонку в df.
df = pd.read_csv(file, sep='t', dtype=str, na_values="", low_memory=False)
row_ids = []
for index, row in df.iterrows():
if (index % 1000) == 0:
print("Row node index: {}".format(str(index)))
caculated_id = get_id(row['name', row['sex']])
row_ids.append(caculated_id)
df['id'] = row_ids
Есть ли способ сделать это намного быстрее, не переходя ряд за рядом?
Добавьте дополнительную информацию на основе предложенных решений:
Комментарии:
1. Не могли бы вы включить функцию
get_id
и образец df?2. Это обычная функция, принимающая ввод и возвращающая все, что угодно. Просто для примера.
3. Как создается идентификатор? Включите небольшой образец фрейма данных. Я не уверен, что
get_id(row['name', row['sex']])
должен делать.4. идентификатор=хэш(имя пол)
5. @marlon — pandas позволяет выполнять операции массово. Предположим
id
, это просто объединениеname
иsex
. Ты мог бы это сделатьdf['id'] = df['name'] df['sex']
. Вместо функции, которая что-то делает с отдельными ячейками, посмотрите, можете ли вы что-то делать с целыми столбцами.
Ответ №1:
Используйте apply
вместо этого:
def func(x):
if (x.name % 1000) == 0:
print("Row node index: {}".format(str(x.name)))
caculated_id = get_id(row['name', row['sex']])
return caculated_id
df['id'] = df.apply(func, axis=1)
Комментарии:
1. Возвращает ли приложение здесь список новых идентификаторов?
2. @марлон Да. Конечно.
3. Я проверю скорость на большом csv-файле.
4. Если моя функция get_xxx() возвращает несколько списков для более общих случаев, она также должна работать?
5. @marlon Да,
apply
возвращает серию всех результатов.
Ответ №2:
Если вы работаете с большим набором данных, это np.vectorize()
должно помочь обойти apply()
накладные расходы, что должно быть немного быстрее.
import numpy as np
v = np.vectorize(lambda x: get_id(x['name'], x['sex']))
df['id'] = v(df)
Редактировать:
Чтобы получить еще большую скорость, вы также можете просто передать функцию get_id
вместо использования лямбда-функции и передать df.*.values
вместо df.*
.
v = np.vectorize(get_id)
df['id'] = v(df['name'].values, df['sex'].values)
Вместо того, чтобы печатать обновления о ходе процесса, попробуйте использовать tqdm
для отображения прогресса индикатор выполнения.
import numpy as np
from tqdm import tqdm
@np.vectorize
def get_id(name, sex):
global pbar
...
pbar.update(1)
...
return
global pbar
with tqdm(total=len(df)) as pbar:
df['id'] = get_id(df['name'].values, df['sex'].values)
Комментарии:
1. Если get_id возвращает несколько списков, v{df} относится к списку списка? get_id может быть переименован в get_new_columns.
2. @marlon да, так и должно быть, в основном это работает так же, как
apply()
. Пожалуйста, попробуйте и дайте мне знать, если это быстрее для вас.3. я буду стараться для скорости.
4. В вашем коде » df » отсутствует во 2-й строке?
5. @marlon нет, это не нужно
df
, чтобы его передавалиv
. Также я добавил в улучшение, не могли бы вы проверить, работает ли это?