我有两个pandas DataFrame,如下所示:
print( a )
foo bar let letval
9 foo1 bar1 let1 a
8 foo2 bar2 let1 b
7 foo3 bar3 let1 c
6 foo1 bar1 let2 z
5 foo2 bar2 let2 y
4 foo3 bar3 let2 x
print( b )
foo bar num numval
0 foo1 bar1 num1 1
1 foo2 bar2 num1 2
2 foo3 bar3 num1 3
3 foo1 bar1 num2 4
4 foo2 bar2 num2 5
5 foo3 bar3 num2 6
我想merge
列[ 'foo', 'bar' ]
上的c = pd.merge( a, b, on=['foo', 'bar'] )
。
如果我只是做prnint( c )
foo bar let letval num numval
0 foo1 bar1 let1 a num1 1
1 foo1 bar1 let1 a num2 4
2 foo1 bar1 let2 z num1 1
3 foo1 bar1 let2 z num2 4
4 foo2 bar2 let1 b num1 2
5 foo2 bar2 let1 b num2 5
6 foo2 bar2 let2 y num1 2
7 foo2 bar2 let2 y num2 5
8 foo3 bar3 let1 c num1 3
9 foo3 bar3 let1 c num2 6
10 foo3 bar3 let2 x num1 3
11 foo3 bar3 let2 x num2 6
,我会得到:
print( c )
foo bar let letval num numval
0 foo1 bar1 let1 a num1 1
1 foo2 bar2 let1 b num1 2
2 foo3 bar3 let1 c num1 3
3 foo1 bar1 let2 z num2 4
4 foo2 bar2 let2 y num2 5
5 foo3 bar3 let2 x num2 6
我想:
c = pd.merge( a, b, left_index=['foo', 'bar'], right_index=['foo', 'bar'] )
我最接近的是:
c.shape = (12,6)
我错过了什么?
为什么我在第一个例子中得到map_ab = { 'num1':'let1', 'num2':'let2' }
b['let'] = b.apply( lambda x: map_ab[x['num']], axis=1 )
c = pd.merge( a, b, on=['foo', 'bar', 'let'] )
print( c )
?
修改
感谢@piRSquared's answer我意识到潜在的问题是没有一个列的组合来做到这一点。因此,之前提出的合并问题不能单一解决。也就是说,问题转化为更简单的问题:
如何在表格之间建立单一的关系?
我用一本字典来解决这个问题,该字典映射了需要对齐的所需输出:
class ExhibitionSurveyObject(models.Model):
owner = models.ForeignKey(User, verbose_name="Owner of this Survey object", blank=False,)
name = models.CharField(max_length=15, blank=False, verbose_name="Survey Object name", help_text="Please give a single word name for your farm",)
farmer_email = models.EmailField(max_length=254, blank=False, verbose_name="Email of the farmer", )
farmer_name = models.CharField(max_length=25, blank=False, verbose_name="Name of the farmer", )
address = models.TextField(help_text="Please provide the address without the postal code", blank=True,)
postal_code = models.CharField(max_length=5, blank=True, default='12043')
size = models.DecimalField(max_digits=9, decimal_places=6, blank=False, )
path = models.CharField(max_length=1000, blank=False)
def setpath(self, x):
self.path = json.dumps(x)
def getpath(self, x):
return json.loads(self.path)
OBJECT_TYPES = (
('FARM', 'Farm'),
('SOLARPANEL', 'Solarpanel'),
('PLAIN', 'plain')
)
object_type = models.CharField(max_length=100, choices=OBJECT_TYPES)
CYCLES = (
('ONCE', 'once'),
('WEEKLY', 'weekly'),
('MONTHLY', 'monthly')
)
cycle = models.CharField(max_length=100, choices=CYCLES)
#To add user's full name in the admin interface for better readability
def get_owner_full_name(self):
return self.owner.get_full_name()
#Works like a verbose_name but for a method
get_owner_full_name.short_description = 'Owners full name'
答案 0 :(得分:2)
您之所以这样做是因为您要合并的列不构成唯一组合。例如,a
的第一行(索引0)行有foo1
和bar1
,但第四行(索引3)也是如此。好的,没关系,但b
有同样的问题。因此,当您匹配b
' s foo1
&对于使用bar1
索引的行,0
匹配两次。匹配foo1
&在bar1
索引的行中3
,它匹配两次。所以你最终得到了这两行的四场比赛。
所以你得到了
a
第0行与b
第0行匹配a
第0行与b
第3行a
第3行与b
第0行匹配a
第3行与b
第3行匹配然后,你的例子再做2次。 3 * 4 == 12
执行此操作并且明确无误的唯一方法是,如果存在多个匹配项,则决定要采用哪种匹配规则。我决定将你的其他一个专栏分组,然后选择第一个专栏。它仍然不符合您的预期输出,但我建议您提供一个不好的例子。
pd.merge( a, b, on=['foo', 'bar']).groupby(['foo', 'bar', 'let'], as_index=False).first()
答案 1 :(得分:1)
您可以使用combine_first:
In[21]:a.combine_first(b)
Out[21]:
bar foo let letval num numval
0 bar1 foo1 let1 a num1 1
1 bar2 foo2 let1 b num1 2
2 bar3 foo3 let1 c num1 3
3 bar1 foo1 let2 z num2 4
4 bar2 foo2 let2 y num2 5
5 bar3 foo3 let2 x num2 6
在第一个示例中,您正在执行inner join
,如果bar
& foo
中的a,b
相等。