替换具有不同大小和多个条件的数据框之间的值

时间:2019-07-29 19:08:15

标签: python pandas dataframe

所以我有2个数据帧,大小不同,分别为df1 = (578, 81)df2 = (1500, 59)df1 exists in df2的所有行以及df2 exists in df1的所有列,我的问题是,我有我想基于6 conditions在df1中更新一个值,因此要更新column X,两个数据帧上的列X1, X2, Y1, Y2, Z1 and Z2上的值必须相等。

在Java上,我会做类似的事情:

for(i=0;i<df1.length;i++){
    for(k=0;k<df2.length;k++){
        if(df1[i][1]==df2[k][1] && df1[i][2]==df2[k][2] ...){
            df1[i][0] = df2[k][0];
    }
}

2 个答案:

答案 0 :(得分:2)

您可以轻松使用numpy.where。而且我认为它在这种情况下也应该效果最好。

假设您具有以下数据框

import pandas as pd

df1=pd.DataFrame({'X':[1,3,4,6,5],
                  'X1':[2,3,4,6,3],
                  'Y1':[4,2,1,51,3],
                  'Z1':[2,3,4,1,5]})

df2=pd.DataFrame({'L':[2,3,4,1,4],
                  'X2':[2,3,4,6,5],
                  'Y2':[4,3,4,6,3],
                  'Z2':[2,2,1,51,3]})

您想根据条件X1==X2 & Y1==Y2 & Z1==Z2更改X的值。还可以说,在这种情况下,您要更新的值来自L列。

您可以像这样使用numpy.where

df1['X']=np.where((df1['X1']==df2['X2'])&(df1['Y1']==df2['Y2'])&(df1['Z1']==df2['Z2']),df2['L'],,df1['X'])

它只会更改第一行,因为只有在那里满足条件。如果满足条件,此函数会将值更改为df2['L'];如果不满足条件,此函数将保留原始值。

详细了解np.where

更新:问题中的数据框不相等。它们没有相等的列也没关系,但是为了比较,行应该相等。以下是两个数据帧不相等的示例,以及在这种情况下如何执行numpy.where

import pandas as pd
import numpy as np

df1=pd.DataFrame({'X':[1,3,4,6,5],
                  'X1':[2,3,4,6,3],
                  'Y1':[4,3,1,51,3],
                  'Z1':[2,3,4,1,5]})

df2=pd.DataFrame({'L':[2,3,4,1,4,5,1],
                  'X2':[2,3,4,6,5,2,3],
                  'Y2':[4,3,4,6,3,8,7],
                  'Z2':[2,3,1,51,3,9,9],
                  'R2':[2,5,1,2,7,3,9]})

#make both the dataframes equal

for i in range(len(df2)-len(df1)):
    df1=df1.append(pd.Series(),ignore_index=True)

df1['X']=np.where((df1['X1']==df2['X2'])&(df1['Y1']==df2['Y2'])&(df1['Z1']==df2['Z2']),df2['L'],df1['X'])

#drop those null values which have been appended above to get back to original
df1=df1.dropna(how='all')    

答案 1 :(得分:0)

6列使行唯一吗? 如果是这样,我将使用merge:

columns_join= ['col1', 'col2', 'col3', 'col4', 'col5', 'col6']
columns_update= ['upd1', 'upd2', 'upd3']

df_merged= df_to_update[columns_join].merge(df_source[columns_join + columns_update], on=columns_join, how='left', suffixes=['', '_src'], indicator='_join_ind')

for col in columns_update:
    df_to_update.loc[df_merged['_join_ind']=='both', col]= df_merged[col + '_src']

# now df_to_update contains the result

如果6个字段不能标识一行(可能导致更多行),则之后需要使合并后的结果唯一,但是在这种情况下,您的Java版本也将始终生成最后一个的值行。 在这种情况下,您可以使用DataFrame.groubylast作为聚合函数。

编辑:如果您需要应用聚合,则最好将聚合应用于采用值的数据框。要使用每个组的最后一个值对它进行汇总,然后再合并,只需将上面的.merge替换为以下行即可:

df_agg= df_source.groupby(columns_join)[columns_update].aggregate('last')
df_merged= df_to_update[columns_join].merge(df_source[columns_join + columns_update], left_on=columns_join, right_index=True, how='left', suffixes=['', '_src'], indicator='_join_ind')