Я практикуюсь с функциями Панды, Лямбды и сталкиваюсь с трудной задачей. У меня уже есть «формально» правильное решение, но абсолютно неэффективное.
Это проблема:
У меня есть Pandas DataFrame df
, что-то вроде этого (код для генерации образца этого в конце этого поста):
id type
0 1003 G
1 1003 A
2 1002 T
3 1002 A
4 1001 A
5 1003 A
6 1002 G
7 1003 A
8 1001 T
9 1001 A
Ожидаемый результат: новый столбец для каждого отдельного типа (A, C, G, T), который содержит количество уникальных идентификаторов, которые в последней строке, которые они отображали в таблице, имеют этот тип.
Возможный вывод - это (отредактировано для соответствия желаемому результату):
id num_A num_C num_G num_T type
0 1003 0 0 1 0 G
1 1003 1 0 0 0 A
2 1002 1 0 0 1 T
3 1002 2 0 0 0 A
4 1001 3 0 0 0 A
5 1003 3 0 0 0 A
6 1002 2 0 1 0 G
7 1003 2 0 1 0 A
8 1001 1 0 1 1 T
9 1001 2 0 1 0 A
Чтобы достичь этой цели, я сделал следующее (, который не работает должным образом, если вы сравните вывод с таблицей, показанной выше ):
Определен временный фрейм данных tmp
, в котором хранится состояние всех возможных идентификаторов (в этом примере максимум 9):
id type_A type_C type_G type_T
0 1001 0 0 0 0
1 1002 0 0 0 0
2 1003 0 0 0 0
3 1004 0 0 0 0
4 1005 0 0 0 0
5 1006 0 0 0 0
6 1007 0 0 0 0
7 1008 0 0 0 0
8 1009 0 0 0 0
Определен итеративный цикл, который проверяет, какой тип каждой строки в df
, а затем обновляет соответственно состояние tmp
DataFrame:
Вот код:
for df_row in range(0, df.shape[0]):
if df.type[df_row] == 'A':
for tmp_row in range(0, tmp.shape[0]):
if tmp.id[tmp_row] == df.id[df_row]:
tmp.type_A[tmp_row] = 1
df.num_A[df_row] = tmp.type_A.sum()
if df.type[df_row] == 'C':
for tmp_row in range(0, tmp.shape[0]):
if tmp.id[tmp_row] == df.id[df_row]:
tmp.type_C[tmp_row] = 1
df.num_C[df_row] = tmp.type_C.sum()
if df.type[df_row] == 'G':
for tmp_row in range(0, tmp.shape[0]):
if tmp.id[tmp_row] == df.id[df_row]:
tmp.type_G[tmp_row] = 1
df.num_G[df_row] = tmp.type_G.sum()
if df.type[df_row] == 'T':
for tmp_row in range(0, tmp.shape[0]):
if tmp.id[tmp_row] == df.id[df_row]:
tmp.type_T[tmp_row] = 1
df.num_T[df_row] = tmp.type_T.sum()
Что я хотел бы понять, так это то, что если использовать лямбда-функции или использовать другой подход, можно ли получить более быстрый результат, который также лучше с точки зрения производительности.
Для создания образца DataFrame, подобного моему, вы можете использовать следующий код (предложения о том, как это настроить, также приветствуются, поэтому я могу узнать больше):
df = pd.DataFrame({'id': np.random.randint(1001, 1004, size=10), \
'type_tmp': np.random.randint(1, 4, size=10), \
'type': '', \
'num_G': 0, 'num_A': 0, 'num_T': 0, 'num_C': 0})
for r in range(0, df.shape[0]):
if df.type_tmp[r] == 1:
df.type[r] = 'G'
if df.type_tmp[r] == 2:
df.type[r] = 'A'
if df.type_tmp[r] == 3:
df.type[r] = 'T'
if df.type_tmp[r] == 4:
df.type[r] = 'C'
df = df.drop(columns='type_tmp')
Временный фрейм данных определяется следующим образом:
tmp = pd.DataFrame({'id': np.arange(1001, 1010), 'type_A': 0, 'type_C': 0, 'type_G': 0, 'type_T': 0})
Спасибо за ваше драгоценное время.