Проверьте, существует ли строка с определенными значениями, и создайте, если она не существует - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть большая таблица с несколькими тысячами исходных точек (столбец A) и несколькими тысячами конечных точек (столбец B) и другими столбцами со значением. Мне нужен эффективный алгоритм в Python, чтобы убедиться, что есть строка для каждой пары происхождения от пункта назначения, и если нет, создать его.

Например, представьте, что у меня есть три исходные точки (1,2,3) и три конечных пункта (1,2,3). В настоящее время в моих данных нет строки для каждой возможной пары между источниками (столбец A) и пунктами назначения (столбец B), и выглядит так:

Index  A      B     Value
0      1      1     V11
1      1      3     V13
2      2      1     V21
3      2      2     V22
4      2      3     V23
5      3      1     V31
6      3      3     V33

Я хочу, чтобы скрипт на Python выглядел так:

Index  A      B     Value
0      1      1     V11
1      1      2     NA
2      1      3     V13
3      2      1     V21
4      2      2     V22
5      2      3     V23
6      3      1     V31
7      3      2     NA
8      3      3     V33

Ответы [ 4 ]

0 голосов
/ 27 апреля 2018

Решения со стеком / unstack или pivot имеют предварительное условие, что все возможные точки должны существовать в столбцах «A» и «B». если в этих двух столбцах отсутствует точка, результат будет неверным. Например, удалив Index = 3 (V22) в исходных данных, получится результат:

In []: df.set_index(['A','B']).unstack().stack(dropna=False).reset_index()
Out[]: 
   A  B Value
0  1  1   V11
1  1  3   V13
2  2  1   V21
3  2  3   V23
4  3  1   V31
5  3  3   V33

Более надежным решением является использование reindex () для принудительного получения результирующих строк с заранее определенными точками и порядком, поэтому не беспокойтесь о возможных пропущенных точках. i.e.:

In []: midx = pd.MultiIndex.from_product([[1,2,3],[1,2,3]],names=list('AB'))
In []: df.set_index(['A','B']).reindex(midx).reset_index()
Out[]: 
   A  B Value
0  1  1   V11
1  1  2   NaN
2  1  3   V13
3  2  1   V21
4  2  2   NaN
5  2  3   V23
6  3  1   V31
7  3  2   NaN
8  3  3   V33
0 голосов
/ 27 апреля 2018

Вы можете использовать:

df.set_index(['A','B'])\
  .unstack()\
  .stack(dropna=False)\
  .reset_index()

Выход:

   A  B Value
0  1  1   V11
1  1  2  None
2  1  3   V13
3  2  1   V21
4  2  2   V22
5  2  3   V23
6  3  1   V31
7  3  2  None
8  3  3   V33

Как это работает:

Сначала вы создаете MultiIndex. Используйте unstack с уровнем по умолчанию -1, самым внутренним индексом, это создает матрицу с A в виде строк и B в качестве столбцов, заполняя эту матрицу совпадающим значением. В местах, где нет соответствующих значений, назначается None / NaN. Теперь мы можем использовать стек с параметром dropna = False, чтобы сохранить все значения, включая значения None / NaN.

0 голосов
/ 27 апреля 2018

Попробуйте pivot и melt

df.pivot(index='A',columns='B',values='Value').reset_index().melt('A').sort_values('A')
Out[338]: 
   A  B value
0  1  1   V11
3  1  2  None
6  1  3   V13
1  2  1   V21
4  2  2   V22
7  2  3   V23
2  3  1   V31
5  3  2  None
8  3  3   V33
0 голосов
/ 27 апреля 2018

Это один из способов использования itertools.product.

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

from itertools import product

maxval = df[['A', 'B']].max().max()

prod = set(product(range(1, maxval+1), range(1, maxval+1)))
existing = set(map(tuple, df[['A', 'B']].values))

additional = pd.DataFrame(np.array(list(prod - existing)), columns=['A', 'B'])

res = pd.concat([df.set_index('Index'), additional], axis=0)\
        .sort_values(['A', 'B'])\
        .reset_index(drop=True)\
        .reset_index()

print(res)

   index  A  B Value
0      0  1  1   V11
1      1  1  2   NaN
2      2  1  3   V13
3      3  2  1   V21
4      4  2  2   V22
5      5  2  3   V23
6      6  3  1   V31
7      7  3  2   NaN
8      8  3  3   V33
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...