Python Pandas: Как использовать словарь для столбца, который содержит список ключей, чтобы создать другой столбец из списка значений - PullRequest
0 голосов
/ 04 сентября 2018

Скажем, у меня есть датафрейм pandas, где один из столбцов - это список ключей. Как создать еще один столбец, значения которого соответствуют этим ключам?

Ниже приведен минимальный пример заявленного фрейма данных и словаря

ex = pd.DataFrame( {'a': [1,2,3], 'b': [[1,2,3], [3, 2, 1], [2, 1, 3]]  }) 
ex.head()

    a    b
0   1   [1, 2, 3]
1   2   [3, 2, 1]
2   3   [2, 1, 3]

din = {1: 'A', 2:'B', 3:'C'}

Как создать другой столбец, который использует словарь для сопоставления каждого значения из каждого списка в столбце b?

Например, я хочу сделать что-то вроде этого:

    a    b           c
0   1   [1, 2, 3] [A, B, C] 
1   2   [3, 2, 1] [C, B, A] 
2   3   [2, 1, 3] [B, A, C] 

Обычно, чтобы сделать что-то подобное, когда столбец не является списком, используется функция карты, как показано ниже

ex['c'] = ex['b'].map(din)

Однако, поскольку столбец b является списком, а не самим ключом, я получаю эту ошибку

TypeError                                 Traceback (most recent call last)
<ipython-input-44-d5b753372a81> in <module>()
----> 1 ex['c'] = ex['b'].map(din)

/usr/local/lib/python3.6/dist-packages/pandas/core/series.py in map(self, arg, na_action)
   2348         if isinstance(arg, Series):
   2349             # arg is a Series
-> 2350             indexer = arg.index.get_indexer(values)
   2351             new_values = algorithms.take_1d(arg._values, indexer)
   2352         else:

/usr/local/lib/python3.6/dist-packages/pandas/core/indexes/base.py in get_indexer(self, target, method, limit, tolerance)
   2682             target = target.astype(object)
   2683             return this.get_indexer(target, method=method, limit=limit,
-> 2684                                     tolerance=tolerance)
   2685 
   2686         if not self.is_unique:

/usr/local/lib/python3.6/dist-packages/pandas/core/indexes/base.py in get_indexer(self, target, method, limit, tolerance)
   2700                                  'backfill or nearest reindexing')
   2701 
-> 2702             indexer = self._engine.get_indexer(target._values)
   2703 
   2704         return _ensure_platform_int(indexer)

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_indexer()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.lookup()

TypeError: unhashable type: 'list'

Ответы [ 2 ]

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

Более пандасийский способ:

ex['c']=ex['b'].apply(lambda x: pd.Series(x).map(din).tolist())
print(ex)

Выход:

   a          b          c
0  1  [1, 2, 3]  [A, B, C]
1  2  [3, 2, 1]  [C, B, A]
2  3  [2, 1, 3]  [B, A, C]

Ваш код не работает, потому что вы назначаете его всему столбцу сразу, а не каждому значению, поэтому вы можете использовать apply для него

Или:

ex['c']=list(map(lambda i: list(map(din.get,i)),ex['b']))

Или, как сказал @jezrael:

ex['c']=list(map(lambda i: [din.get(a) for a in i],ex['b']))
0 голосов
/ 04 сентября 2018

Поскольку каждое значение в столбце является списком, вы не можете использовать map напрямую. Вам необходимо отобразить каждое значение в списке следующим образом:

ex['c']=ex['b'].apply(lambda x: [din.get(v) for v in x])

    a   b           c
0   1   [1, 2, 3]   [A, B, C]
1   2   [3, 2, 1]   [C, B, A]
2   3   [2, 1, 3]   [B, A, C]

Или согласно предложению Zero:

ex['c'] = ex['b'].apply(lambda L: list(map(din.get, L)))

Или согласно предложению jezrael:

ex['c'] = [list(map(din.get, x)) for x in ex['b']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...