检查是否存在具有特定值的行,如果不存在则创建

时间:2018-04-26 21:02:42

标签: python pandas dataframe

我有一个包含数千个原点(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 :(得分:4)

这是使用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

答案 1 :(得分:4)

您可以使用:

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。使用默认级别-1为最内层索引的unstack,这将创建一个矩阵,其中A为行,B为列,使用匹配的值填充该矩阵。在没有匹配值的地方,分配无/ NaN。现在,我们可以使用带有参数dropna = False的堆栈来保留所有值,包括None / NaN值。

答案 2 :(得分:2)

尝试SELECT * FROM dblink('dbname=mydb options=-csearch_path=', 'select proname, prosrc from pg_proc') AS t1(proname name, prosrc text) WHERE proname LIKE 'bytea%'; pivot

melt

答案 3 :(得分:0)

具有stack / 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()来强制生成具有预定义点和顺序的行,因此不必担心任何潜在的缺失点。即:

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