Pandas仅合并顺序匹配对

时间:2017-05-16 12:44:37

标签: python pandas merge

表1

Oid, T1
10, 1493955900309445045
10, 1493955900321006000
10, 1493955900322255462
11, 14910000

表2:

Oid,T2
10, 1493955900309206537
10, 1493955900320695981
11, 1490000


Expected merge output
Oid,T1,T2
10, 1493955900309445045,1493955900309206537
10, 1493955900321006000,1493955900320695981
#ignored 10, 1493955900322255462 #mapped nowhere
11, 14910000,1490000

基本上合并匹配的第一个实例并忽略剩余。 我知道数据是按顺序排列的(有些值缺少表2),所以我需要忽略这些情况。为简单起见,我们可以假设表1是某个任务的开始,表2包含某个任务的结束。有一天任务可能会结束但不会结束!我认为这可以通过索引

来完成

附加:

假设我们只想在两个Oid中的条目数相同时才合并。 预期的合并输出变为

Oid,T1,T2
#ignored all Oid = 10,because there count in table 1=3,table2=3
11, 14910000,1490000

另一个例子

>>> df1
   Oid    ts
0   10  1000
1   10  1001
2   20  2000
3   20  2001
4   30  3000
5   40  4000
>>> df2
   Oid   ts2
0   10  1006
1   10  1007
2   10  1008
3   20  2005
4   20  2004
5   30  3003
6   40  4004
7   40  4008

Expected Output
Oid    ts    ts2
20    2000    2005
20    2001    2004
30    3000    3003

我认为使用value_counts应该有所帮助,我做了

>>> df1.Oid.value_counts()
20    2
10    2
30    1
40    1
Name: Oid, dtype: int64
>>> df2.Oid.value_counts()
10    3
20    2
40    2
30    1

现在只需要20和30,因为只有计数匹配。我想我需要创建从df1和df2过滤然后合并的好订单列表。

@jezrael你的答案似乎适用于整个专栏而不是Oid专栏中的每个独特条目

1 个答案:

答案 0 :(得分:1)

您可以使用cumcountOid列然后merge来计算重复次数。最后按drop删除了帮助列new

df1['new'] = df1.groupby('Oid').cumcount()
df2['new'] = df2.groupby('Oid').cumcount()

print (df1)
   Oid                   T1  new
0   10  1493955900309445045    0
1   10  1493955900321006000    1
2   10  1493955900322255462    2
3   11             14910000    0

print (df2)
   Oid                   T2  new
0   10  1493955900309206537    0
1   10  1493955900320695981    1
2   11              1490000    0    

df = pd.merge(df1, df2, on=['Oid','new']).drop('new', axis=1)
print (df)
   Oid                   T1                   T2
0   10  1493955900309445045  1493955900309206537
1   10  1493955900321006000  1493955900320695981
2   11             14910000              1490000

编辑要检查列是否相同,请使用equals

if df1['Oid'].equals(df2['Oid']):
    print ('eq')
    #another code
else:
    print ('no')
    #another code

另一种可能的解决方案是,列中的测试值与Series.eq(与==)和all相同:

if (df1['Oid'].eq(df2['Oid'])).all():
    print ('eq')
    #another code
else:
    print ('no')
    #another code

EDIT1:

首先获得具有相同长度的oids

a = df1.Oid.value_counts()
b = df2.Oid.value_counts()

df1 = df1.set_index('Oid')
df2 = df2.set_index('Oid')

c = pd.concat([a,b], axis=1, keys=('a','b'))
oids = c.index[c['a'] == c['b']]
print (oids)
Int64Index([20, 30], dtype='int64')

然后按oidsconcat选择:

df3 = pd.concat([df1.loc[oids],df2.loc[oids]], axis=1).reset_index()
print (df3)
   Oid    ts   ts2
0   20  2000  2005
1   20  2001  2004
2   30  3000  3003