'Python, pandas group one dataframe by the results from another of different size
I have two dataframes, df_DD carries all my data, and df_GS carries the ranges of data that I want to break df_DD into. df_GS is much shorter than df_DD, I want to group all the df_DD by df_GS for when the ranges are equated.
Small range of df_GS
From To DHID
0 69.0 88.5 CR22-200
1 88.5 90.0 CR22-200
2 90.0 99.0 CR22-200
3 99.0 100.5 CR22-200
4 100.5 112.5 CR22-200
5 112.5 114.0 CR22-200
6 114.0 165.0 CR22-200
for i in range(len(df_GS)):
df_DD['Samples'].loc[(df_DD[From] >= df_GS[From].iloc[i]) & (df_DD[To] <= df_GS[To].iloc[i]) & (df_DD[DHID]==df_GS[DHID].iloc[i])] = i+1
Here is an output of df_DD
Samples From To DHID
0 1 69.0 70.5 CR22-200
1 1 70.5 72.0 CR22-200
2 1 72.0 73.5 CR22-200
3 1 73.5 75.0 CR22-200
4 1 75.0 76.5 CR22-200
5 1 76.5 78.0 CR22-200
6 1 78.0 79.5 CR22-200
7 1 79.5 81.0 CR22-200
8 1 81.0 82.5 CR22-200
9 1 82.5 84.0 CR22-200
10 1 84.0 85.5 CR22-200
11 1 85.5 87.0 CR22-200
12 1 87.0 88.5 CR22-200
13 2 88.5 90.0 CR22-200
14 3 90.0 91.5 CR22-200
15 3 91.5 93.0 CR22-200
The code above does what I want it to by creating a new column named Samples giving values a sample index, after which I can use the groupby function. But I wanted to know if there was a better way to do this cause it's quite cumbersome.
Solution 1:[1]
With merge_asof you can merge on the closest key instead of an exact key.
df = pd.DataFrame({"from": [69.0, 88.5, 90.0], "DHID":['CR22-1', 'CR22-2','CR22-3']})
df['samples'] = df.index + 1
df_DD = pd.DataFrame({"from": [69.0, 75.1, 86.7, 88.5, 90.0]})
result = pd.merge_asof(df_DD, df, on='from')
The default direction is backward, so it merges df's row where from is the closest value that is less or equal to the df_DD's from column.
This code gives you the result:
from DHID samples
0 69.0 CR22-1 1
1 75.1 CR22-1 1
2 86.7 CR22-1 1
3 88.5 CR22-2 2
4 90.0 CR22-3 3
Optional notes
You can keep the original to column or add a new one and also you can set the column order you want at the end like this:
result['to'] = result["from"].shift(-1)
result = result[['samples', 'from', 'to', 'DHID']]
That gives you:
samples from to DHID
0 1 69.0 75.1 CR22-1
1 1 75.1 86.7 CR22-1
2 1 86.7 88.5 CR22-1
3 2 88.5 90.0 CR22-2
4 3 90.0 NaN CR22-3
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
