反复添加计算所得的列,然后仅将新数据添加到Pandas数据框(python 3.7.1)

时间:2019-03-14 11:41:23

标签: python pandas loops dataframe merge

我有一个初始数据帧df1:

    df1 = pd.DataFrame(np.array([[1, 'B', 'C', 'D', 'E'], [2, 'B', 'C', 'D', 'E'], [3, 'B', 'C', 'D', 'E'], [4, 'B', 'C', 'D', 'E'], [5, 'B', 'C', 'D', 'E']]), columns=['a', 'b', 'c', 'd', 'e'])

        a   b   c   d   e
    0   1   B   C   D   E
    1   2   B   C   D   E
    2   3   B   C   D   E
    3   4   B   C   D   E
    4   5   B   C   D   E

然后我根据df1列值计算一些新参数,创建一个新df2并与列名“ a”上的df1合并。

    df2 = pd.DataFrame(np.array([[1, 'F', 'G'], [2, 'F', 'G']]), columns=['a', 'f', 'g'])

        a   f   g
    0   1   F   G
    1   2   F   G
    df1 = pd.merge(df1, df2,  how='left', left_on=['a'], right_on = ['a'])

        a   b   c   d   e   f   g
    0   1   B   C   D   E   F   G
    1   2   B   C   D   E   F   G
    2   3   B   C   D   E   NaN NaN
    3   4   B   C   D   E   NaN NaN
    4   5   B   C   D   E   NaN NaN

这工作得很好,但是在另一个循环事件中,我创建了一个与df2具有相同列的df3,但是在这种情况下合并不起作用,它没有考虑到df1中已经存在相同的列。

重要提示:这仅出于说明目的,有数千个新数据帧要添加,每个循环步骤一个。

    df3 = pd.DataFrame(np.array([[3, 'F', 'G']]), columns=['a', 'f', 'g'])

        a   f   g
    0   3   F   G
df1 = pd.merge(df1, df3,  how='left', left_on=['a'], right_on = ['a'])

        a   b   c   d   e   f_x g_x f_y g_y
    0   1   B   C   D   E   F   G   NaN NaN
    1   2   B   C   D   E   F   G   NaN NaN
    2   3   B   C   D   E   NaN NaN F   G
    3   4   B   C   D   E   NaN NaN NaN NaN
    4   5   B   C   D   E   NaN NaN NaN NaN

我只是一个人来填补已经存在的空白。这种方法会创建新的列(f_x, g_x, f_y, g_y)

添加和联系也无法正常工作,因为它们会重复信息(“ a”上的重复行)。

有关如何解决此问题的任何建议?将df1df2合并后,与df3合并后的最终结果应为:

        a   b   c   d   e   f   g
    0   1   B   C   D   E   F   G
    1   2   B   C   D   E   F   G
    2   3   B   C   D   E   F   G
    3   4   B   C   D   E   NaN NaN
    4   5   B   C   D   E   NaN NaN

最终,所有列将在循环期间填充,因此第一个添加的(df2)将添加新的列,从df3开始,仅新数据填充所有NaN。循环看起来像这样:

df1 = pd.DataFrame(np.array([[1, 'B', 'C', 'D', 'E'], [2, 'B', 'C', 'D', 'E'], [3, 'B', 'C', 'D', 'E'], [4, 'B', 'C', 'D', 'E'], [5, 'B', 'C', 'D', 'E']]), columns=['a', 'b', 'c', 'd', 'e'])
for num, item in enumerate(df1['a']):
    #compute df[num] (based on values on df1)
    df1 = pd.merge(df1, df[num],  how='left', left_on=['a'], right_on = ['a'])

3 个答案:

答案 0 :(得分:3)

一个可能的解决方案是concat个小的DataFrame,然后merge一次:

df4 = pd.concat([df2, df3])
print (df4)
   a  f  g
0  1  F  G
1  2  F  G
0  3  F  G

df1 = pd.merge(df1, df4,  how='left', on = 'a')
print (df1)
   a  b  c  d  e    f    g
0  1  B  C  D  E    F    G
1  2  B  C  D  E    F    G
2  3  B  C  D  E    F    G
3  4  B  C  D  E  NaN  NaN
4  5  B  C  D  E  NaN  NaN

另一种可能的解决方案是将DataFrame.combine_firstDataFrame.set_index一起使用:

df1 = (df1.set_index('a')
         .combine_first(df2.set_index('a'))
         .combine_first(df3.set_index('a')))
print (df1)
   b  c  d  e    f    g
a                      
1  B  C  D  E    F    G
2  B  C  D  E    F    G
3  B  C  D  E    F    G
4  B  C  D  E  NaN  NaN
5  B  C  D  E  NaN  NaN

答案 1 :(得分:1)

另一种方法也是使用fillna然后删除不再需要的多余列:

# Fill NaN with the extra columns value
df1.f_x.fillna(df1.f_y, inplace=True)
df1.g_x.fillna(df1.g_y, inplace=True)

   a  b  c  d  e  f_x  g_x  f_y  g_y
0  1  B  C  D  E    F    G  NaN  NaN
1  2  B  C  D  E    F    G  NaN  NaN
2  3  B  C  D  E    F    G    F    G
3  4  B  C  D  E  NaN  NaN  NaN  NaN
4  5  B  C  D  E  NaN  NaN  NaN  NaN

# Slice of the last two columns
df1 = df1.iloc[:, :-2]
# Rename the columns correctly
df1.columns = df1.columns.str.replace('_x', '')

输出

   a  b  c  d  e    f    g
0  1  B  C  D  E    F    G
1  2  B  C  D  E    F    G
2  3  B  C  D  E    F    G
3  4  B  C  D  E  NaN  NaN
4  5  B  C  D  E  NaN  NaN

答案 2 :(得分:0)

在与df3的合并中,我只使用df1的子集,或者我可以保留原始df1的副本。

  1. 子集:

    df1.fillna(pd.merge(df1.loc(1)['a':'e'], df3, how='left',
                        left_on=['a'], right_on = ['a']),
               inplace=True)
    
  2. 原始数据的副本

    df1_orig = df1           # before merging with df2
    ...
    df1.fillna(pd.merge(df1_orig, df3, how='left',
                        left_on=['a'], right_on = ['a']),
               inplace=True)
    
相关问题