python - 合并两个具有重叠范围的数据框并计算按类别分组的重叠
问题描述
基于这个答案
,我有两个大数据框(100K 行),df Assay 有值,df Strat 有“类型”。我想根据深度将 Strat 中的“类型”分配给 Assay 中的列。深度以深度“从”和深度“到”列的形式给出。“类型”也由深度“从”和“到”定义。但它们不是相同的间隔。分析深度可能跨越多个 Strat 类型。
我想将 Strat '类型'分配给 Assay df,如果有多种类型,请尝试捕获该信息。
我想遍历数据以填充每个 HOLE_ID 的类型列。
生成示例数据:
import pandas as pd
import numpy as np
Assay=pd.DataFrame(np.array([['Hole_1',1.0,2.5,0.001],['Hole_1',2.5,5.0,0.005],['Hole_1',5.0,7.0,0.002],['Hole_1',7.0,10.0,0.001],['Hole_2',1.0,3.0,0.001],['Hole_2',3.0,5.0,0.005],['Hole_2',5.0,7.0,0.002],['Hole_2',7.0,10.0,0.001]]),columns=['HOLE_ID','FROM', 'TO', 'val'])
Strat=pd.DataFrame(np.array([['Hole_1',0.0,4.0,'A'],['Hole_1',4.0,5.0,'B'],['Hole_1',5.0,6.5,'C'],['Hole_1',6.5,8.0,'D'],['Hole_1',8.0,10.0,'E'],['Hole_2',0.0,4.0,'A'],['Hole_2',4.0,5.1,'B'],['Hole_2',5.1,6.0,'C'],['Hole_2',6.0,8.0,'D'],['Hole_2',8.0,10.0,'E']]),columns=['HOLE_ID','FROM', 'TO', 'Type'])
Assay
Out[1]:
HOLE_ID FROM TO val
0 Hole_1 1.0 2.5 0.001
1 Hole_1 2.5 5.0 0.005
2 Hole_1 5.0 7.0 0.002
3 Hole_1 7.0 10.0 0.001
4 Hole_2 1.0 3.0 0.001
5 Hole_2 3.0 5.0 0.005
6 Hole_2 5.0 7.0 0.002
7 Hole_2 7.0 10.0 0.001
Strat
Out[2]:
HOLE_ID FROM TO Type
0 Hole_1 0.0 4.0 A
1 Hole_1 4.0 5.0 B
2 Hole_1 5.0 6.5 C
3 Hole_1 6.5 8.0 D
4 Hole_1 8.0 10.0 E
5 Hole_2 0.0 4.0 A
6 Hole_2 4.0 5.1 B
7 Hole_2 5.1 6.0 C
8 Hole_2 6.0 8.0 D
9 Hole_2 8.0 10.0 E
所需输出的示例:
HOLE_ID FROM TO val Type
0 Hole_1 1.0 2.5 0.001 A 100%
1 Hole_1 2.5 5 0.005 A 60%,B 44%
2 Hole_1 5.0 7.0 0.002 C 80%, D 20%
3 Hole_1 7.0 10.0 0.001 D 30%, E 70%
4 Hole_2 1.0 3.0 0.001 A 100%
5 Hole_2 3.0 5.0 0.005 A 50%, B50%
6 Hole_2 5.0 7.0 0.002 B 5%, C 45%, D 50%
7 Hole_2 7.0 10.0 0.001 D 30% E 70%
我的尝试在下面,但不起作用。我不太擅长循环,我进行了一些有希望的尝试,但代码似乎永远运行(注意,我的实际数据集是 ~100k 行和 1500 HOLE_ID,所以可能对我的系统要求很高)。
我添加了 np.arange 以便我可以使用浮点数(0.1 m 增量来生成辅助系列)并且我认为我有百分比计算但我有点超出我的深度。
进行一些预处理以确保仅使用匹配的孔 ID(实际数据很大,并且还包含示例数据集中未包含的其他列。)
assay_Hole_IDs =Assay['HOLE_ID'].unique().tolist()
strat_Hole_IDS =Strat['HOLE_ID'].unique().tolist()
Strat=Strat[Strat['HOLE_ID'].isin(assay_Hole_IDs)]
Assay=Assay[Assay['HOLE_ID'].isin(assay_Hole_IDs)]
assay_Hole_IDs =Assay['HOLE_ID'].unique().tolist()
strat_Hole_IDS =Strat['HOLE_ID'].unique().tolist()
检查是否没有附加值
j=set(assay_Hole_IDs).symmetric_difference(set(strat_Hole_IDS))
print len(j)
j
然后:
all_holes= Strat['HOLE_ID'].unique().tolist()
def getType(row):
for hole in all_holes:
df=Strat.loc[Strat['HOLE_ID']==hole]
units = df.set_index('Type').apply(lambda row: pd.Series(
np.arange(row.FROM, row.TO,0.1)), axis=1).stack()\
.reset_index(level=1, drop=True)
gr = units[units.ge(row.FROM) & units.lt(row.TO)].groupby(level=0)
if gr.ngroups == 1:
return gr.ngroup().index[0]
txt = []
counts = []
pct=[]
for key, grp in gr:
siz = grp.size
un = 'unit' if siz == 1 else 'units'
counts.append(float(siz))
for x in counts:
p=(float(x)/float(sum(counts))*100)
pct.append(float(p))
return pct
然后:
assay['Type'] = assay.groupby('HOLE_ID').apply(getType)
谁能明白为什么这不起作用?
解决方案
def group(df1):
df2 = Strat[Strat['HOLE_ID']==df1.iloc[0]['HOLE_ID']]
df1[['FROM','TO']] = df1[['FROM','TO']].astype(float)
df2[['FROM','TO']] = df2[['FROM','TO']].astype(float)
temp = pd.concat([df1[['FROM','TO']],df2[['FROM','TO']]]).unstack().reset_index(drop=True) \
.drop_duplicates().sort_values().reset_index(drop=True) \
.to_frame(name='FROM').merge(df2, how='outer').ffill()
temp['TO'] = temp.shift(-1)['FROM']
def tobins(x):
agg = temp[(x.FROM <= temp.FROM) & (temp.FROM < x.TO)].groupby('Type') \
.apply(lambda y: y['TO'].max() - y['FROM'].min()).reset_index(name='res')
agg.res = agg.Type + ' ' + (agg.res/agg.res.sum()).map('{:.0%}'.format)
return '; '.join(agg.res.tolist())
df1['Type'] = df1.apply(tobins,axis=1)
return df1
Assay.groupby('HOLE_ID').apply(group)
HOLE_ID FROM TO val Type
0 Hole_1 1.0 2.5 0.001 A 100%
1 Hole_1 2.5 5.0 0.005 A 60%; B 40%
2 Hole_1 5.0 7.0 0.002 C 75%; D 25%
3 Hole_1 7.0 10.0 0.001 D 33%; E 67%
4 Hole_2 1.0 3.0 0.001 A 100%
5 Hole_2 3.0 5.0 0.005 B 100%
6 Hole_2 5.0 7.0 0.002 C 75%; D 25%
7 Hole_2 7.0 10.0 0.001 D 33%; E 67%
关键是用两个表中的所有点 FROM 和 TO 构建 temp DataFrame。因为HOLE_ID = 'Hole_1'
它看起来如下。现在我们可以为 Assay (x) 的每一行获取临时表的那些行,(x.FROM <= temp.FROM < x.TO)
按类型对它们进行分组,计算份额并连接到结果格式
FROM HOLE_ID TO Type
0 0.0 Hole_1 1.0 A
1 1.0 Hole_1 2.5 A
2 2.5 Hole_1 4.0 A
3 4.0 Hole_1 5.0 B
4 5.0 Hole_1 6.5 C
5 6.5 Hole_1 7.0 D
6 7.0 Hole_1 8.0 D
7 8.0 Hole_1 10.0 E
8 10.0 Hole_1 NaN E
推荐阅读
- python - python将几个数据框与日期合并
- git - 将一个 git repo 分成两个单独的 repo,作为两个不同的代码库
- javascript - Jquery .replaceWith() 没有用更新的文本正确更新
- chatbot - Watson Assistant 字体在 csv 下载和上传时发生变化
- c# - 如何在不使用 ClosedXML 评估公式的情况下从 excel 单元格显示值中读取
- java - 尝试组合 orderByChild() 和 startAt() 时使用 null 获取值
- ios - UIViewController 在设置中更新相机权限后关闭
- java - 从组合框中获取 ID (java)
- c++ - 未找到 QtResource 文件中的文件
- coldfusion - 由于可能的代码注入,评估()的冷融合替代品?