【问题标题】:How to modify the values in a dataframe based on the values from another dataframe in an efficient way?如何以有效的方式根据来自另一个数据帧的值修改数据帧中的值?
【发布时间】:2018-10-03 08:51:28
【问题描述】:

我有 2 个这样的数据框:

import pandas as pd
data1 = {'Col1':['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'],
        'Col2':[3.409836, 2.930693, 2.75, 3.140845, 2.971429, 2.592593, 2.6, 3.1875, 2.857143, 0.714286]}
df1 = pd.DataFrame(data1, columns=['Col1', 'Col2'])

data2 = {'Col1':['B', 'F', 'I'],
         'Col2':[23.45, 32.57, 19.85]}
df2 = pd.DataFrame(data2, columns=['Col1', 'Col2'])

我想用df2 中的值修改df1Col2 的值。这是我的代码:

for i in range(len(df2)):
    for j in range(len(df1)):
        if df2['Col1'][i]==df1['Col1'][j]:
            df1['Col2'][j]=df2['Col2'][i]

代码有效:

但问题是,此代码对于大型数据帧会很慢,因为它具有复杂性O(len(df1)*len(df2))。如何以更快、更有效的方式合并这 2 个数据帧?

我尝试使用外连接合并数据帧,但它没有产生正确的结果 - 它保留了两个值:

pd.merge(df1, df2, how='outer')

内连接产生一个空白数据框,左连接产生与df1相同的数据框,右连接产生与df2相同的数据框。

【问题讨论】:

    标签: python pandas dataframe join merge


    【解决方案1】:

    如果只使用一列,请使用 map:

    df1['Col2'] = df1['Col1'].map(df2.set_index('Col1')['Col2']).fillna(df1['Col2'])
    print (df1)
      Col1       Col2
    0    A   3.409836
    1    B  23.450000
    2    C   2.750000
    3    D   3.140845
    4    E   2.971429
    5    F  32.570000
    6    G   2.600000
    7    H   3.187500
    8    I  19.850000
    9    J   0.714286
    

    如果可以使用多个列,请使用 merge 和左连接并指定列 Col1

    cols = df1.columns.difference(['Col1'])
    orig_cols = [f'{x}_' for x in cols]
    
    df = pd.merge(df1, df2, how='left', on='Col1', suffixes=('_',''))
    print (df)
      Col1     Col2_   Col2
    0    A  3.409836    NaN
    1    B  2.930693  23.45
    2    C  2.750000    NaN
    3    D  3.140845    NaN
    4    E  2.971429    NaN
    5    F  2.592593  32.57
    6    G  2.600000    NaN
    7    H  3.187500    NaN
    8    I  2.857143  19.85
    9    J  0.714286    NaN
    

    然后用原始列替换添加列的缺失值并最后删除它们:

    df[cols] = df[cols].fillna(df[orig_cols].rename(columns=lambda x: x.strip('_')))
    df = df.drop(orig_cols, axis=1)
    
    print (df)
      Col1       Col2
    0    A   3.409836
    1    B  23.450000
    2    C   2.750000
    3    D   3.140845
    4    E   2.971429
    5    F  32.570000
    6    G   2.600000
    7    H   3.187500
    8    I  19.850000
    9    J   0.714286
    

    【讨论】:

    • 您能否也编辑答案以添加使用多列的解决方案?
    • @Kristada673 - 我试试看,请检查一下。
    • 太棒了!还有一件事 - 我如何在df1 中添加另一个名为Col3 的列,如果值已根据df2 修改,则表示modified,如果不是,则表示original
    • @Kristada673 - 我认为 merge 是它的参数 - df = pd.merge(df1, df2, how='left', on='Col1', suffixes=('_',''), indicator=True)
    • @Kristada673 - bith 表示值在两个 df 中,因此被替换
    【解决方案2】:

    试试这个代码:

    df4=df3.Col3.isnull()
    df3=pd.merge(df1, df2,how='outer')
    df4=df3[df3.Col3.isnull()]
    df5=df3[df3.Col3.notnull()]
    df5.Col2=df5.Col3
    df6=df4.append(df5)
    df6=df6.drop('Col3',axis=1)
    

    df6 是您要查找的输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-26
      • 1970-01-01
      • 2019-08-20
      • 2018-04-27
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 2019-07-10
      相关资源
      最近更新 更多