Hey, auch wenn es schon etwas her ist, beschäftigt mich das Thema noch sehr. Es gibt noch ein kleines Problem und ich hoffe du (oder jemand anderes) kann mir dabei helfen. Dafür habe ich extra ein Beispiel angefertigt, was sofort ausgeführt werden kann. Ich hoffe es schreckt nicht ab. Die Frage die ich habe, ist eigentlich ganz simpel und kann evtl. sehr leicht beantwortet werden.
Zuerst die Daten:
Code: Alles auswählen
array_data=([[ 50.56419 , 8.67667 , 2. , 160. ],
[ 50.5643136, 8.6772816, 3. , 89. ],
[ 50.5646274, 8.6763909, 0. , 259. ],
[ 50.5661047, 8.6765931, 1. , 100. ],
[ 50.5663442, 8.6575205, 1. , 117. ],
[ 50.56686 , 8.67598 , 1. , 95. ],
[ 50.56747 , 8.67604 , 2. , 199. ],
[ 50.56762 , 8.6702799, 0. , 148. ],
[ 50.5693473, 8.6640855, -1. , 50. ],
[ 50.5693473, 8.6640855, 0. , 111. ],
[ 50.5705819, 8.6597279, 2. , 183. ],
[ 50.57067 , 8.65694 , 2. , 257. ],
[ 50.57075 , 8.65748 , 1. , 211. ],
[ 50.57075 , 8.65748 , 1. , 292. ],
[ 50.5722461, 8.6598248, 2. , 142. ],
[ 50.57254 , 8.65895 , 1. , 116. ],
[ 50.57259 , 8.6592 , 2. , 228. ],
[ 50.5731636, 8.667609 , 1. , 181. ],
[ 50.5737814, 8.6720067, 0. , 173. ],
[ 50.5740356, 8.6718179, 1. , 5. ],
[ 50.5746321, 8.6831284, 3. , 202. ],
[ 50.5747453, 8.6765588, 4. , 119. ],
[ 50.5748992, 8.6611471, 2. , 260. ],
[ 50.5748992, 8.6611471, 3. , 102. ],
[ 50.575 , 8.65985 , 2. , 267. ],
[ 50.5751 , 8.66027 , 2. , 7. ],
[ 50.5751 , 8.66027 , 2. , 56. ],
[ 50.57536 , 8.67741 , 1. , 194. ],
[ 50.57536 , 8.67741 , 1. , 282. ],
[ 50.5755255, 8.6884584, 0. , 276. ],
[ 50.5755273, 8.674282 , 3. , 167. ],
[ 50.57553 , 8.6826 , 2. , 273. ],
[ 50.5755973, 8.6847492, 0. , 168. ],
[ 50.5756757, 8.6846139, 4. , 255. ],
[ 50.57572 , 8.65965 , 0. , 66. ],
[ 50.57591 , 8.68175 , 1. , 187. ]])
Daraus machen wir schnell ein Dataframe:
Code: Alles auswählen
df = pd.DataFrame(data=array_data) # convert back to dataframe
df.rename(columns={0: 'latitude', 1: 'longitude', 2:'floor', 3:'id'}, inplace=True) # rename columns
Nun haben wir die Daten wie sie mir im Jupyter Notebook vorliegen.
Zuerst definieren wir die Funktion zur Berechnung der Abstände:
Code: Alles auswählen
def calculate_distance(lat1, lon1, lat2, lon2):
"""
Calculate the shortest distance between two points given by the latitude and
longitude.
"""
earth_radius = 6373 # Approximate / in km.
lat1 = radians(lat1)
lon1 = radians(lon1)
lat2 = radians(lat2)
lon2 = radians(lon2)
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
return earth_radius * c # in km.
Soweit so gut!
Als nächstes kommt die Funktion um die es hier eigentlich gehen soll. Ich möchte Leute die nicht am selben Ort leben (latitude, longitude, floor) in groups zuordnen. Das heißt, am Ende soll jeder in genau einer group sein. Die Größe einer group besteht immer aus 3 Personen. Diese haben, wie gesagt, unterschiedliche Ortkoordinaten.
Code: Alles auswählen
def main(all_persons, max_distance_parameter):
assert len(all_persons) % 9 == 0
all_persons.set_index("id", drop=False, inplace=True)
all_persons["host"] = np.nan
all_persons["group"] = np.nan
Streufaktor = 0.0001
max_distance = max_distance_parameter
group_number = 0
group = []
for _, candidate in all_persons.iterrows():
if len(group) == 3:
for person in group:
all_persons.at[person["id"], "group"] = group_number
group_number += 1
group = []
if len(group) == 0:
group.append(candidate)
else:
for person in group:
distance = calculate_distance(
candidate["latitude"],
candidate["longitude"],
person["latitude"],
person["longitude"],
)
distance = distance
if candidate['floor'] == -1: # consider the floor when calculating the distance
distance = distance + Streufaktor + 0.001
elif candidate['floor'] == 0:
distance = distance + Streufaktor + 0.002
elif candidate['floor'] == 1:
distance = distance + Streufaktor + 0.003
elif candidate['floor'] == 2:
distance = distance + Streufaktor + 0.004
elif candidate['floor'] == 3:
distance = distance + Streufaktor + 0.005
elif candidate['floor'] == 4:
distance = distance + Streufaktor + 0.006
elif candidate['floor'] == 5:
distance = distance + Streufaktor + 0.007
elif candidate['floor'] == 6:
distance = distance + Streufaktor + 0.008
elif candidate['floor'] == 7:
distance = distance + Streufaktor + 0.009
elif candidate['floor'] == 8:
distance = distance + Streufaktor + 0.010
elif candidate['floor'] == 9:
distance = distance + Streufaktor + 0.011
elif candidate['floor'] == 10:
distance = distance + Streufaktor + 0.012
elif candidate['floor'] == 11:
distance = distance + Streufaktor + 0.013
elif candidate['floor'] == 12:
distance = distance + Streufaktor + 0.014
elif candidate['floor'] == 13:
distance = distance + Streufaktor + 0.015
elif candidate['floor'] == 14:
distance = distance + Streufaktor + 0.016
else:
distance = distance + Streufaktor + 0.017
if 0 < distance <= max_distance:
group.append(candidate)
break
Nun wende ich die Funktion an. Aus irgendwelchen Gründen, funktioniert die Funktion am besten wenn ich einen besonders hohen Wert für max_distance angebe:
Da immer 3 Personen nicht einer group zugewiesen werden, mache ich das nun im letzten Schritt:
Code: Alles auswählen
all_persons = all_persons.reset_index(drop=True)
# get all rows where column "group" is NaN
nan_rows = all_persons[all_persons['group'].isnull()]
nan_index = nan_rows.index # get index of all rows where column "group" is NaN
# replace all values where column "group" is NaN with value x
for index in nan_index:
all_persons.iloc[index, all_persons.columns.get_loc('group')] = (max_group_value[0] +1)
Eigentlich wäre ich nun fertig.
Es gibt jedoch ein Problem:
Wenn ich das dataframe teste auf duplicate, stelle ich fest, dass es Leute gibt, die in der selben group sind und die selben Ortskoordinaten teilen. Aber das sollte ja eigentlich durch die Funktion sort_people() verhindert werden. Was läuft da schief?
Code: Alles auswählen
# check if function works!
duplication_parameters = ['latitude', 'longitude', 'floor', 'group']
duplicate_bool = all_persons.duplicated(subset = duplication_parameters, keep=False)
duplicate = all_persons.loc[duplicate_bool == True]
duplicate.sort_values(duplication_parameters, ascending=True, inplace=False )
Ich hoffe ihr könnt mir helfen!