2016-03-03 4 views
0

Я пытаюсь отфильтровать один DataFrame значениями другого DataFrame, но не могу заставить его работать, поскольку фильтр-by-DataFrame имеет другой размер, чем те, которые будут фильтроваться DataFrame , Я думал, что мне нужно использовать set_index, чтобы как-то совместить оба DataFrames, но это может быть неправильно.Сравнение DataFrames разной длины

import pandas as pd 
df1 = pd.DataFrame({'a': [1, 1, 2, 3, 3, 4], 'b': [5, 3, 6, 2, 6, 4]}) 
df2 = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [3, 5, 6, 3]}) 
dfa = df1.set_index('a') 
>>> dfa 
    b 
a 
1 5 
1 3 
2 6 
3 2 
3 6 
4 4 

dfb = df2.set_index('a') 

>>> dfa[dfa['b'] <= dfb['b']] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/core/ops.py", line 699, in wrapper 
    raise ValueError('Series lengths must match to compare') 
ValueError: Series lengths must match to compare 

Ожидаемый DataFrame будет pd.DataFrame({'a': [1, 3, 3], 'b': [3, 2, 6]}):

a b 
0 1 3 
1 3 2 
2 3 6 

(все <a, b> строки исчезают из df1, для которого значение b в df2 является < = значение b в df1 и оба a значения совпадают для df1 и df2).

Update

Более наивный способ не работает, либо ...

>>> df1[(df1['a'] == df2['a']) & (df1['b'] <= df2['b'])] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/core/ops.py", line 699, in wrapper 
    raise ValueError('Series lengths must match to compare') 
ValueError: Series lengths must match to compare 

ответ

2

Вы можете использовать reindex_like для Allign свой второй dataframe до df1 размера, а затем использовать вашу попытку с добавлением isin метод вместо сравнения df1['a'] с df2['a']:

df3 = df2.reindex_like(df1) 

In [93]: df1[(df3['a'].isin(df1['a'])) & (df1['b'] <= df3['b'])] 
Out[93]: 
    a b 
1 1 3 
2 2 6 
3 3 2 
2

Вот один из способов:

>>> df1[df1.b <= df1.a.map(dfb.b)] 
    a b 
1 1 3 
3 3 2 
4 3 6 

Это проще в использовании, чем df1dfa потому что вам нужно map, который не работает прямо на индексы (только на серии). Если вам абсолютно необходимо использовать dfa вместо dfb, вам придется изменить вторую часть сравнения на dfa.reset_index().a.map(dfb.b).

0

Я думаю, что самый простой способ - использовать merge и привести столбец df2 в df1.

>>> df2['c'] = df2['b'] 
>>> pd.merge(df1, df2, how='left', on=['a']) 
    a b_x b_y c 
0 1 5 3 3 
1 1 3 3 3 
2 2 6 5 5 
3 3 2 6 6 
4 3 6 6 6 
5 4 4 3 3 

а затем просто сделать df1[df1['b_x'] <= df1['c']].