0

I tried to rework my question in order to match the quality criteria and spent more time in trying to achieve the result on my own.

Given are two DataFrames

a = DataFrame({"id" : ["id1"] * 3 + ["id2"] * 3 + ["id3"] * 3,
               "left" : [6, 2, 5, 2, 1, 4, 5, 2, 4],
               "right" : [1, 3, 4, 6, 5, 3, 6, 3, 2]               
             })

b = DataFrame({"id" : ["id1"] * 6 + ["id2"] * 6 + ["id3"] * 6,
               "left_and_right" : range(1,7) * 3,  
               "boolen" : [0, 0, 1, 0, 1, 0, 1, 0, 0 , 1, 1, 0, 0, 0, 1, 0, 0, 1]
             })

The expected result is

result = DataFrame({"id" : ["id1"] * 3 + ["id2"] * 3 + ["id3"] * 3,
                    "left"  : [6, 2, 5, 2, 1, 4, 5, 2, 4],
                    "right"  : [1, 3, 4, 6, 5, 3, 6, 3, 2],
                    "NEW": [0, 1, 1, 0, 1, 1, 1, 1, 0]               
                  })

So I want to check in each row of DataFrame b if there is a row in DataFrame a where a.id == b.id AND then look up if b.left_and_right is in (==) a.left OR a.rigtht.
If such a row is found and b.boolen is True/1 for either the value of a.left or a.right, the value of a.NEW in this row should be also True/1.

I hope the example illustrates it better than my words.

To sum it up: I want to look up if in each row where id is the same for both DataFrames whether b.boolen is True/1 for a value in b.left_and_right and if this value is in a.left or in a.right, the new value in a.NEW should also be TRUE/1.

I have tried using the pd.match() and pd.merge() function in combination with & and | operators but could not achieve the wanted result.

Some time ago I had asked a very simillar question dealing with a simillar problem in R (data was organized in a slightly other way, so it was a bit different) but now I fail using the same approach in python.
Related question: Conditional matching of two lists with multi-column data.frames

Thanks

4

1 回答 1

3

只需使用带有 & (and) 和 | 的布尔掩码 (或者):

In [11]: (a.A == b.A) & ((a.B == b.E) | (a.C == b.E)) # they all satisfy this requirement!
Out[11]: 
0    True
1    True
2    True
3    True
dtype: bool

In [12]: b.D[(a.A == b.A) & ((a.B == b.E) | (a.C == b.E))]
Out[12]: 
0    0
1    1
2    0
3    0
Name: D, dtype: int64

In [13]: a['NEW'] = b.D[(a.A == b.A) & ((a.B == b.E) | (a.C == b.E))]

In [14]: a
Out[14]: 
     A  B  C  NEW
0  foo  1  4    0
1  goo  2  3    1
2  doo  3  1    0
3  boo  4  2    0

更新略有不同的问题:

In [21]: merged = pd.merge(a, b, on='id')

In [22]: matching = merged[(merged.left == merged.left_and_right) | (merged.right == merged.left_and_right)]

In [23]: (matching.groupby(['id', 'left', 'right'])['boolen'].sum()).reset_index()
Out[23]: 
    id  left  right  boolen
0  id1     2      3       1
1  id1     5      4       1
2  id1     6      1       0
3  id2     1      5       2
4  id2     2      6       0
5  id2     4      3       1
6  id3     2      3       1
7  id3     4      2       0
8  id3     5      6       1

注意这里有一个 2,所以也许你想关心那些 > 0。

In [24]: (matching.groupby(['id', 'left', 'right'])['boolen'].sum() > 0).reset_index()
Out[24]: 
    id  left  right boolen
0  id1     2      3   True
1  id1     5      4   True
2  id1     6      1  False
3  id2     1      5   True
4  id2     2      6  False
5  id2     4      3   True
6  id3     2      3   True
7  id3     4      2  False
8  id3     5      6   True

您可能希望将布尔列重命名为 NEW。

于 2013-09-03T23:26:56.043 回答