Pandas - вычислить новое значение на основе перекрестной ссылки с другим столбцом - PullRequest
0 голосов
/ 05 апреля 2019

Я пытаюсь вычислить новые значения в столбце, у которого есть перекрестные ссылки на другой столбец.

>>> import pandas as pd
>>> df = pd.DataFrame( {"A":[0., 100., 80., 40., 0., 60.], 
                        "B":[12,  12,   3,  19,  3,  19]} )
>>> df
       A   B
0    0.0  12
1  100.0  12
2   80.0   3
3   40.0  19
4    0.0   3
5   60.0  19

Я хочу найти все значения в столбце A, которые равны 0, найти соответствующиезначение в столбце B, затем измените все значения столбца A, имеющие одинаковое значение столбца B, согласно некоторой функции.Например, в приведенном выше примере я хотел бы изменить первые два значения столбца A, df.A[0] и df.A[1], соответственно, 0 и 100., на 0,5 и 99,5, поскольку df.A[0] равно 0. И он имеетто же значение df.B[0] = 12 в столбце B, что и df.B[1] = 12.

df
      A   B
0   0.5  12
1  99.5  12
2  79.5   3
3  40.0  19
4   0.5   3
5  60.0  19

Я пытался объединить функции loc, aggregate, groupby и mask, но у меня ничего не получается.Является ли единственный путь для цикла for?


РЕДАКТИРОВАТЬ: расширенный пример, чтобы лучше проиллюстрировать намерение.

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

Это будет работать:

import pandas as pd

df = pd.DataFrame( {"A":[0., 100., 40., 60.], "B":[12, 12, 19, 19]} )

def f(series):
    return (series + 0.5).where(series == 0, series - 0.5)

B_value = df.loc[df['A'] == 0, 'B'][0]
df.loc[df['B'] == B_value, 'A'] = df.loc[df['B'] == B_value, 'A'].transform(f)

print(df)

Вывод:

      A   B
0   0.5  12
1  99.5  12
2  40.0  19
3  60.0  19

Вы можете передать произвольную функцию в transform.

Возможно, есть более чистый путьсделать это;это кажется мне немного грязным.

0 голосов
/ 06 апреля 2019

Я нашел рабочее решение, хотя, вероятно, не оптимальное.Я объединяю группы в группы, фильтрую и преобразую для получения нужного ряда, а затем заменяю результат в исходном кадре данных.

import pandas as pd
df = pd.DataFrame( {"A":[0., 100., 80., 40., 0., 60.], 
                    "B":[12,  12,   3,  19,  3,  19]} )
u = ( df.groupby(by="B",  sort=False)
         .filter(lambda x: x.A.min() == 0, dropna=False)
         .A.transform( lambda x: (x+0.5).where(x == 0, x - 0.5) ) 
    )
df.loc[pd.notnull(u), "A"] = u

дает следующие результаты

print("\ninitial df\n",df,"\n\nintermediate series\n",u,"\n\nfinal result",df)

initial df
        A   B
0    0.0  12
1  100.0  12
2   80.0   3
3   40.0  19
4    0.0   3
5   60.0  19

intermediate series
 0     0.5
1    99.5
2    79.5
3     NaN
4     0.5
5     NaN
Name: A, dtype: float64

final result       A   B
0   0.5  12
1  99.5  12
2  79.5   3
3  40.0  19
4   0.5   3
5  60.0  19
...