Панды заменяют несколько значений - PullRequest
0 голосов
/ 07 сентября 2018

Ниже приведен пример кадра данных

>>> df = pd.DataFrame({'a': [1, 1, 1, 2, 2],  'b':[11, 22, 33, 44, 55]})
>>> df
      a   b
   0  1  11
   1  1  22
   2  1  33
   3  2  44
   4  3  55

Теперь я хотел обновить / заменить значения b, которые сопоставляются в столбце из другого dict на основе индекса

например:

match = {1:[111, 222], 2:[444, 555]}

выход:

      a   b
   0  1  111
   1  1  222
   2  1  33  <-- ignores this bcz not enough values to replace in match dict for 1 
   3  2  444
   4  3  555

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Вот один из способов. Идея состоит в том, чтобы рассчитать совокупное количество по группам и использовать его для фильтрации строк. Используйте itertools.chain для создания единого массива значений. Наконец, используйте pd.DataFrame.loc и логическое индексирование для установки значений.

from itertools import chain

count = df.groupby('a').cumcount() + 1

m1 = df['a'].isin(match)
m2 = count.le(df['a'].map(match).map(len))
values = list(chain.from_iterable(match.values()))

df.loc[m1 & m2, 'b'] = values

print(df)

   a    b
0  1  111
1  1  222
2  1   33
3  2  444
4  2  555
0 голосов
/ 07 сентября 2018

Вы можете использовать функцию pop списка:

import pandas as pd


def pop(default, lst):
    try:
        return lst.pop()
    except IndexError:
        return default


df = pd.DataFrame({'a': [1, 1, 1, 2, 2], 'b': [11, 22, 33, 44, 55]})

match = {1: [111, 222], 2: [444, 555]}

df['b'] = df[['a', 'b']].apply(lambda e: pop(e[1], match[e[0]]), axis=1)

print(df)

выход

   a    b
0  1  222
1  1  111
2  1   33
3  2  555
4  2  444

если порядок должен быть сохранен, вы всегда можете выдвинуть первый элемент:

def pop(default, lst):
    try:
        return lst.pop(0)
    except IndexError:
        return default

выход

   a    b
0  1  111
1  1  222
2  1   33
3  2  444
4  2  555

UPDATE

Более быстрый (неразрушающий) способ - использовать deque :

def pop(default, lst):
    try:
        return lst.popleft()
    except IndexError:
        return default

match_deque = {k: deque(v[:]) for k, v in match.items()}

df['b'] = df[['a', 'b']].apply(lambda e: pop(e[1], match_deque[e[0]]), axis=1)

print(df)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...