有条件合并pd.数据帧

2024-04-25 03:57:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道这在熊猫身上是否可行:

  • df2,我想创建new1new2。你知道吗
  • new1作为可以从df1中找到与列A匹配的最新日期 和B
  • new2作为可以从df1中找到的与列A匹配的最新日期 但不是B
  • 我设法得到了new1,但没有new2。你知道吗

代码:

import pandas as pd

d1 = [['1/1/19', 'xy','p1','54'], ['1/1/19', 'ft','p2','20'], ['3/15/19', 'xy','p3','60'],['2/5/19', 'xy','p4','40']]

df1 = pd.DataFrame(d1, columns = ['Name', 'A','B','C']) 

d2 =[['12/1/19', 'xy','p1','110'], ['12/10/19', 'das','p10','60'], ['12/20/19', 'fas','p50','40']]

df2 = pd.DataFrame(d2, columns = ['Name', 'A','B','C'])

d3 = [['12/1/19', 'xy','p1','110','1/1/19','3/15/19'], ['12/10/19', 'das','p10','60','0','0'], ['12/20/19', 'fas','p50','40','0','0']]

dfresult = pd.DataFrame(d3, columns = ['Name', 'A','B','C','new1','new2']) 

更新了!你知道吗


Tags: columnsnamedataframed2d1pddf1df2
2条回答

IIUC,您想向df2添加两列:new1new2。你知道吗

首先我修改了两件事:

df1 = pd.DataFrame(d1, columns = ['Name1', 'A','B','C']) 

df2 = pd.DataFrame(d2, columns = ['Name2', 'A','B','C'])

df1.Name1 = pd.to_datetime(df1.Name1)

为了便于使用,将Name重命名为Name1Name2。然后我把Name1变成了一个真实的日期,这样我们就可以按组获得最大日期。你知道吗

然后,我们在A列上合并df2和df1。这将为我们提供与该列匹配的行

aux = df2.merge(df1, on='A')

当两个数据帧上的B列相同时,我们从中得到Name1

df2['new1'] = df2.index.map(aux[aux.B_x==aux.B_y].Name1).fillna(0)

如果它们不同,我们得到每个A组的最大日期:

df2['new2'] = df2.A.map(aux[aux.B_x!=aux.B_y].groupby('A').Name1.max()).fillna(0)

输出:

      Name2    A    B    C                 new1                 new2
0   12/1/19   xy   p1  110  2019-01-01 00:00:00  2019-03-15 00:00:00
1  12/10/19  das  p10   60                    0                    0
2  12/20/19  fas  p50   40                    0                    0

您可以通过以下方式实现:

  • 标准合并基于
  • 删除所有与B值匹配的条目
  • 日期排序
  • 在上删除重复项,保留最后日期(注意:假设日期是日期格式,而不是字符串!)你知道吗
  • 在id上重新合并

因此:

source = df1.copy()  # renamed
v = df2.merge(source, on='A', how='left')  # get all values where df2.A == source.A
v = v[v['B_x'] != v['B_y']]  # drop entries where B values are the same
nv = v.sort_values(by=['Name_y']).drop_duplicates(subset=['Name_x'], keep='last')
df2.merge(nv[['Name_y', 'Name_x']].rename(columns={'Name_y': 'new2', 'Name_x': 'Name'}),
          on='Name', how='left')  # keeps non-matching, consider inner

这将产生:

Out[94]: 
       Name    A    B    C     new2
0   12/1/19   xy   p1  110  3/15/19
1  12/10/19  das  p10   60      NaN
2  12/20/19  fas  p50   40      NaN

我最初的想法是这样做。可悲的是,它并不优雅。一般来说,这种确定某个值的方法不受欢迎,主要是因为它无法扩展,而且数据量大,速度特别慢。你知道吗

def find_date(row, source=df1):  # renamed df1 to source
    t = source[source['B'] != row['B']]
    t = t[t['A'] == row['A']]
    return t.sort_values(by='date', ascending=False).iloc[0]

df2['new2'] = df2.apply(find_date, axis=1)

相关问题 更多 >