Python 熊猫基于df1中表示df2间隔的列检索值
我有一个结构化的数据帧DF1:Python 熊猫基于df1中表示df2间隔的列检索值,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个结构化的数据帧DF1: import pandas as pd df = pd.DataFrame({'id': [1, 2], 'name': ['A', 'B'], 'ex': ['A1', 'B1'], 'init': ['1,3,5,7,', '10,12,15,17,20,'], 'end':['2,4,6,8,', '15,18,21,24,32']}, columns=['id', 'name', 'ex', 'init', 'end']) print df id na
import pandas as pd
df = pd.DataFrame({'id': [1, 2], 'name': ['A', 'B'], 'ex': ['A1', 'B1'], 'init': ['1,3,5,7,', '10,12,15,17,20,'], 'end':['2,4,6,8,', '15,18,21,24,32']}, columns=['id', 'name', 'ex', 'init', 'end'])
print df
id name ex init end
1 A A1 1,3,5,7, 2,4,6,8,
2 B B1 10,12,15,17,20, 15,18,21,24,32
...
init和end列表示间隔(init end),因此:A->(1,2)、(3,4)、(5,6)、(7,8)、B->(10,15)、(12,18)、(15,21)、(17,24)、(20,32),。。。
另一方面,还有另一个数据帧DF2也表示间隔:
import pandas as pd
df2 = pd.DataFrame({'id': [1, 2], 'init': ['3', '16'], 'end':['6', '22']}, columns=['id', 'init', 'end'])
print df2
id init end
1 3 6
2 16 22
...
是否有任何智能且有效的方法来检查DF1的哪些范围包含DF2中的范围?在本例中,输出将是一个新的DF3:
id name ex ranges
1 A A1 (3,4), (5,6)
2 B B1 (12,18),(15,21),(17,24)
我对此有点困惑,希望能得到帮助。提前谢谢 以下是一个可能的解决方案:
import pandas as pd
df1 = pd.DataFrame({'id': [1, 2], 'name': ['A', 'B'], 'ex': ['A1', 'B1'], 'init': ['1,3,5,7,', '10,12,15,17,20,'], 'end':['2,4,6,8,', '15,18,21,24,32']}, columns=['id', 'name', 'ex', 'init', 'end'])
df2 = pd.DataFrame({'id': [1, 2], 'init': ['3', '16'], 'end':['6', '22']}, columns=['id', 'init', 'end'])
df1.set_index('id', inplace=True)
df2.set_index('id', inplace=True)
df = df1.copy()
df[['init2', 'end2']] = df2
# Per-row function
def proc_row(row):
# Make list of int pairs
intervs = zip(map(int, filter(None, row.init.split(','))), map(int, filter(None, row.end.split(','))))
# Range object to check numbers are in interval - use xrange in Python 2
r = range(int(row.init2), int(row.end2) + 1)
# Discard pairs out of interval
return list(filter(lambda interv: interv[0] in r or interv[1] in r, intervs))
# Process rows
df['ranges'] = df.apply(proc_row, axis=1)
# Drop unnecesary columns
for k in ['init', 'end', 'init2', 'end2']: del df[k]
print(df)
输出:
name ex ranges
id
1 A A1 [(3, 4), (5, 6)]
2 B B1 [(12, 18), (15, 21), (17, 24), (20, 32)]
这就是我要做的
df['init'],df['end']=df.init.str.split(','),df.end.str.split(',')
df
Out[1915]:
id name ex init end
0 1 A A1 [1, 3, 5, 7] [2, 4, 6, 8]
1 2 B B1 [10, 12, 15, 17, 20] [15, 18, 21, 24, 32]
s=df.init.str.len()
s
Out[1917]:
0 4
1 5
Name: init, dtype: int64
NewDF=pd.DataFrame({'id':df.id.repeat(s),'name':df.name.repeat(s),'ex':df.ex.repeat(s),'init':df.init.sum(),'end':df.end.sum()})
s2=NewDF.merge(df2.set_index('id').stack().reset_index(),on='id').loc[lambda x : (x['end']>=x[0])&(x[0]>=x['init'])]
s2['New']=tuple(zip(s2.init,s2.end))
s2.groupby(['ex','id']).New.apply(list)
Out[1943]:
ex id
A1 1 [(3, 4), (5, 6)]
B1 2 [(12, 18), (15, 21), (17, 24), (20, 32)]
Name: New, dtype: object
对于id相同的行,
df1
中的init
和end
列只能与df2
中的init
和end
列进行检查,对吗?(顺便说一句,第二行打印的df2
应该以id
2
开头,而不是1
对吗?)Hello@jdehesa,是的,只检查了具有相同id的行。我修复了df2的id,感谢警告!在df2中,init=16,end=22,输出是如何得到这些区间的:(12,18),(15,21),(17,24)?(16,22)部分包含在这些区间中?数字总是整数?让我用一个真实的例子来检查!提前谢谢你!!