Pandas заменить строки на основе нескольких условий - PullRequest
1 голос
/ 15 апреля 2020

Возьмем, к примеру, следующий кадр данных:

df = pd.DataFrame({"val":np.random.rand(8),
                   "id1":[1,2,3,4,1,2,3,4],
                   "id2":[1,2,1,2,2,1,2,2],
                   "id3":[1,1,1,1,2,2,2,2]})

Я хотел бы заменить строки id2, где id3 не равняется произвольной ссылке, на соответствующие значения id2, которые имеют одинаковый id1

У меня есть решение, которое частично работает, но не работает с использованием 2-го условия (replcae id2 на основе тех же значений, что и id1, когда id3 равен эталону). Это препятствует тому, чтобы мое решение было очень надежным, как обсуждено ниже.

import pandas as pd
import numpy as np

df = pd.DataFrame({"val":np.random.rand(8),
                   "id1":[1,2,3,4,1,2,3,4],
                   "id2":[1,2,1,2,2,1,2,2],
                   "id3":[1,1,1,1,2,2,2,2]})

reference = 1
df.loc[df['id3'] != reference, "id2"] = df[df["id3"]==reference]["id2"].values
print(df)

Вывод:

        val  id1  id2  id3
0  0.580965    1    1    1
1  0.941297    2    2    1
2  0.001142    3    1    1
3  0.479363    4    2    1
4  0.732861    1    1    2
5  0.650075    2    2    2
6  0.776919    3    1    2
7  0.377657    4    2    2

Это решение работает, но только при условии, что id3 имеет два разных значения. Если есть три значения id3, то есть

df = pd.DataFrame({"val":np.random.rand(12),
                   "id1":[1,2,3,4,1,2,3,4,1,2,3,4],
                   "id2":[1,2,1,2,2,1,2,2,1,1,2,2],
                   "id3":[1,1,1,1,2,2,2,2,3,3,3,3]})

Ожидаемый / желаемый результат:

         val  id1  id2  id3
0   0.800934    1    1    1
1   0.505645    2    2    1
2   0.268300    3    1    1
3   0.295300    4    2    1
4   0.564372    1    1    2
5   0.154572    2    2    2
6   0.591691    3    1    2
7   0.896055    4    2    2
8   0.275267    1    1    3
9   0.840533    2    2    3
10  0.192257    3    1    3
11  0.543342    4    2    3

Тогда, к сожалению, мое решение перестает работать. Если бы кто-нибудь мог дать несколько советов, как обойти эту проблему, я был бы очень признателен.

1 Ответ

2 голосов
/ 15 апреля 2020

Если столбец id1 подобен счетчику групп, создайте помощник Series по reference, отфильтруйте группу и сначала DataFrame.set_index, а затем используйте Series.map:

reference = 1
s = df[df['id3'] == reference].set_index('id1')['id2']
df['id2'] = df['id1'].map(s)
print (df)
         val  id1  id2  id3
0   0.986277    1    1    1
1   0.873392    2    2    1
2   0.509746    3    1    1
3   0.271836    4    2    1
4   0.336919    1    1    2
5   0.216954    2    2    2
6   0.276477    3    1    2
7   0.343316    4    2    2
8   0.862159    1    1    3
9   0.156700    2    2    3
10  0.140887    3    1    3
11  0.757080    4    2    3

Если не столбец счетчика, создайте новый с помощью GroupBy.cumcount:

reference = 1

df['g'] = df.groupby('id3').cumcount()
s = df[df['id3'] == reference].set_index('g')['id2']
df['id2'] = df['g'].map(s)
print (df)
         val  id1  id2  id3  g
0   0.986277    1    1    1  0
1   0.873392    2    2    1  1
2   0.509746    3    1    1  2
3   0.271836    4    2    1  3
4   0.336919    1    1    2  0
5   0.216954    2    2    2  1
6   0.276477    3    1    2  2
7   0.343316    4    2    2  3
8   0.862159    1    1    3  0
9   0.156700    2    2    3  1
10  0.140887    3    1    3  2
11  0.757080    4    2    3  3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...