#pandas
Вопрос:
У меня есть фрейм данных, который выглядит так:
df_segments =
id seg_length
15 000b994d-1a6b-4698-a270-b0f671b1e612 16.3
11 000b994d-1a6b-4698-a270-b0f671b1e612 1.1
3 000b994d-1a6b-4698-a270-b0f671b1e612 1.1
7 000b994d-1a6b-4698-a270-b0f671b1e612 16.3
31 016490a8-8740-4205-bfe4-c9fe45e853d3 1.0
27 016490a8-8740-4205-bfe4-c9fe45e853d3 1.4
19 016490a8-8740-4205-bfe4-c9fe45e853d3 1.4
23 016490a8-8740-4205-bfe4-c9fe45e853d3 1.0
39 05290fe1-ead2-462b-bbec-a7669eed7883 1.1
35 05290fe1-ead2-462b-bbec-a7669eed7883 1.4
47 05290fe1-ead2-462b-bbec-a7669eed7883 1.1
43 05290fe1-ead2-462b-bbec-a7669eed7883 1.4
63 0537a9e3-09c4-459c-a6e4-25694cfbacbd 1.1
59 0537a9e3-09c4-459c-a6e4-25694cfbacbd 1.4
51 0537a9e3-09c4-459c-a6e4-25694cfbacbd 1.4
55 0537a9e3-09c4-459c-a6e4-25694cfbacbd 1.1
71 05577c2e-da7d-4753-bba6-66762385e159 1.0
67 05577c2e-da7d-4753-bba6-66762385e159 5.4
79 05577c2e-da7d-4753-bba6-66762385e159 1.0
75 05577c2e-da7d-4753-bba6-66762385e159 5.4
1475 5a104c86-327e-466f-b14a-6953cacddcbb 0.5
1479 5a104c86-327e-466f-b14a-6953cacddcbb 0.5
1487 5a104c86-327e-466f-b14a-6953cacddcbb 0.5
1483 5a104c86-327e-466f-b14a-6953cacddcbb 0.5
2287 8e853797-a7f3-4605-8848-f6b211f9b055 2.1
2283 8e853797-a7f3-4605-8848-f6b211f9b055 2.1
2279 8e853797-a7f3-4605-8848-f6b211f9b055 2.1
2275 8e853797-a7f3-4605-8848-f6b211f9b055 2.1
3351 c1120018-c626-4c1b-81a5-476ce38f346b 0.6
3347 c1120018-c626-4c1b-81a5-476ce38f346b 1.2
3359 c1120018-c626-4c1b-81a5-476ce38f346b 0.5
3355 c1120018-c626-4c1b-81a5-476ce38f346b 1.2
Все id
они имеют четыре ряда. Для большинства id
удаление дубликатов приводит к появлению двух строк. Но в течение нескольких id
секунд может произойти одно из двух:
- Либо все строки равны, и в этом случае
drop_duplicates()
получится одна строка. drop_duplicates()
с результатом в три или для строк, потому что все значенияseg_length
разные.
Однако все seg_length
они имеют длину сторон в прямоугольнике (или очень близко к нему) и квадратах. Итак, я хотел бы сделать следующие вещи:
О. Если все строки по идентификатору имеют одинаковое seg_length
значение, сохраните две строки.
B. Замените два самых больших (соответственно, самых маленьких) значения (по идентификатору) на их среднее значение. Другими словами:
df_segments =
id seg_length
3351 c1120018-c626-4c1b-81a5-476ce38f346b 0.6
3347 c1120018-c626-4c1b-81a5-476ce38f346b 1.2
3359 c1120018-c626-4c1b-81a5-476ce38f346b 0.5
3355 c1120018-c626-4c1b-81a5-476ce38f346b 1.2
стал бы:
df_segments =
id seg_length
3351 c1120018-c626-4c1b-81a5-476ce38f346b 0.55
3347 c1120018-c626-4c1b-81a5-476ce38f346b 1.2
3359 c1120018-c626-4c1b-81a5-476ce38f346b 0.55
3355 c1120018-c626-4c1b-81a5-476ce38f346b 1.2
В качестве альтернативы, используйте min/max
, если это проще:
df_segments =
id seg_length
3351 c1120018-c626-4c1b-81a5-476ce38f346b 0.6
3347 c1120018-c626-4c1b-81a5-476ce38f346b 1.2
3359 c1120018-c626-4c1b-81a5-476ce38f346b 0.6
3355 c1120018-c626-4c1b-81a5-476ce38f346b 1.2
Я пытался использовать np.where
и определять условия, но безрезультатно. Я также попытался создать отдельный фрейм данных с идентификаторами, количество которых не равнялось 2, после удаления дубликатов из исходного фрейма данных, df_segments
но я оказался в той же ситуации.
Если у кого-то есть идея, я был бы благодарен за понимание.
Ответ №1:
Если я хорошо понимаю, вы хотите усреднить значения 2 на 2 в каждом идентификаторе. Это также происходит, чтобы сделать то, что вы хотите, когда оно в 4 раза превышает одно и то же значение.
>>> averages = df.groupby('id')['seg_length'].apply(
... lambda s: s.sort_values().groupby([0, 0, 1, 1]).mean()
... )
>>> averages
id
000b994d-1a6b-4698-a270-b0f671b1e612 0 1.10
1 16.30
016490a8-8740-4205-bfe4-c9fe45e853d3 0 1.00
1 1.40
05290fe1-ead2-462b-bbec-a7669eed7883 0 1.10
1 1.40
0537a9e3-09c4-459c-a6e4-25694cfbacbd 0 1.10
1 1.40
05577c2e-da7d-4753-bba6-66762385e159 0 1.00
1 5.40
5a104c86-327e-466f-b14a-6953cacddcbb 0 0.50
1 0.50
8e853797-a7f3-4605-8848-f6b211f9b055 0 2.10
1 2.10
c1120018-c626-4c1b-81a5-476ce38f346b 0 0.55
1 1.20
Name: seg_length, dtype: float64
Если вы хотите сохранить исходную форму, вы можете использовать transform
(на обоих groupby
):
>>> replaced_seglengths = df.groupby('id')['seg_length'].transform(
... lambda s: s.sort_values().groupby([0, 0, 1, 1]).transform('mean')
... )
>>> replaced_seglengths
15 1.10
11 1.10
3 16.30
7 16.30
31 1.00
27 1.00
19 1.40
23 1.40
39 1.10
35 1.10
47 1.40
43 1.40
63 1.10
59 1.10
51 1.40
55 1.40
71 1.00
67 1.00
79 5.40
75 5.40
1475 0.50
1479 0.50
1487 0.50
1483 0.50
2287 2.10
2283 2.10
2279 2.10
2275 2.10
3351 0.55
3347 0.55
3359 1.20
3355 1.20
Наконец, замените столбец в фрейме данных:
>>> df['seg_length'] = replaced_seglengths
>>> df
id seg_length
15 000b994d-1a6b-4698-a270-b0f671b1e612 1.10
11 000b994d-1a6b-4698-a270-b0f671b1e612 1.10
3 000b994d-1a6b-4698-a270-b0f671b1e612 16.30
7 000b994d-1a6b-4698-a270-b0f671b1e612 16.30
31 016490a8-8740-4205-bfe4-c9fe45e853d3 1.00
27 016490a8-8740-4205-bfe4-c9fe45e853d3 1.00
19 016490a8-8740-4205-bfe4-c9fe45e853d3 1.40
23 016490a8-8740-4205-bfe4-c9fe45e853d3 1.40
39 05290fe1-ead2-462b-bbec-a7669eed7883 1.10
35 05290fe1-ead2-462b-bbec-a7669eed7883 1.10
47 05290fe1-ead2-462b-bbec-a7669eed7883 1.40
43 05290fe1-ead2-462b-bbec-a7669eed7883 1.40
63 0537a9e3-09c4-459c-a6e4-25694cfbacbd 1.10
59 0537a9e3-09c4-459c-a6e4-25694cfbacbd 1.10
51 0537a9e3-09c4-459c-a6e4-25694cfbacbd 1.40
55 0537a9e3-09c4-459c-a6e4-25694cfbacbd 1.40
71 05577c2e-da7d-4753-bba6-66762385e159 1.00
67 05577c2e-da7d-4753-bba6-66762385e159 1.00
79 05577c2e-da7d-4753-bba6-66762385e159 5.40
75 05577c2e-da7d-4753-bba6-66762385e159 5.40
1475 5a104c86-327e-466f-b14a-6953cacddcbb 0.50
1479 5a104c86-327e-466f-b14a-6953cacddcbb 0.50
1487 5a104c86-327e-466f-b14a-6953cacddcbb 0.50
1483 5a104c86-327e-466f-b14a-6953cacddcbb 0.50
2287 8e853797-a7f3-4605-8848-f6b211f9b055 2.10
2283 8e853797-a7f3-4605-8848-f6b211f9b055 2.10
2279 8e853797-a7f3-4605-8848-f6b211f9b055 2.10
2275 8e853797-a7f3-4605-8848-f6b211f9b055 2.10
3351 c1120018-c626-4c1b-81a5-476ce38f346b 0.55
3347 c1120018-c626-4c1b-81a5-476ce38f346b 0.55
3359 c1120018-c626-4c1b-81a5-476ce38f346b 1.20
3355 c1120018-c626-4c1b-81a5-476ce38f346b 1.20
Комментарии:
1. Это именно то, что я искал! Спасибо!
Ответ №2:
использовать np.select([conditions],[solutions])
условия
condition1=df2.groupby('id')['seg_length'].apply(lambda x:x.duplicated(keep=False))
condition2=df2.groupby('id')['seg_length'].apply(lambda x:~x.duplicated(keep=False))
Решение
sol1=df2['seg_length']
sol2=(df2.loc[condition2,'seg_length'].sum(0))/2
df2['newseg_length']=np.select([condition1,condition2],[sol1,sol2])
id seg_length newseg_length
3351 c1120018-c626-4c1b-81a5-476ce38f346b 0.6 0.55
3347 c1120018-c626-4c1b-81a5-476ce38f346b 1.2 1.20
3359 c1120018-c626-4c1b-81a5-476ce38f346b 0.5 0.55
3355 c1120018-c626-4c1b-81a5-476ce38f346b 1.2 1.20
Комментарии:
1. Спасибо. Это решило часть 2 проблемы.