Группа людей, которые имеют разные места - PullRequest
0 голосов
/ 15 марта 2020

Мне нужна помощь. Моя функция группировать людей на самом деле не работает. Проблема довольно проста:

У меня есть кадр данных со следующими столбцами:

  • широта
  • долгота
  • пол

Эти столбцы являются случайными местоположениями людей. Длина фрейма данных кратна 9 (в данном примере это 36. В действительности это намного больше).

Я хочу сгруппировать людей по следующей идее:

Сначала я создаю новый столбец с именем «группа». Люди, которые живут близко друг к другу (в соответствии с координатами), назначаются на определенный c номер группы (1, 2 3, ...). Каждая группа состоит из 3 человек.

Теперь сложная часть: Люди с одинаковыми координатами не могут быть в одной группе !

Вот как я это сделал:

Вот данные:

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.       ]])

Преобразование массива в фрейм данных и переименование столбцов:

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

Теперь у нас есть фрейм данных. С помощью следующих функций я пытался сгруппировать людей:

Сначала нам нужно найти способ, чтобы определить расстояния до людей:

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.

И вот основная функция. Я пытаюсь группировать людей, если они НЕ находятся в одном и том же месте:

def sort_people(all_persons, max_distance_parameter):

    '''
    People in the same group have different location!
    '''

    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

    scattering_factor= 0.0001  # to seperate same floor numbers
    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 + scattering_factor + 0.001
                elif candidate['floor'] == 0:
                  distance = distance + scattering_factor + 0.002
                elif candidate['floor'] == 1:
                  distance = distance + scattering_factor + 0.003
                elif candidate['floor'] == 2:
                  distance = distance + scattering_factor + 0.004
                elif candidate['floor'] == 3:
                  distance = distance + scattering_factor + 0.005
                elif candidate['floor'] == 4:
                  distance = distance + scattering_factor + 0.006
                elif candidate['floor'] == 5:
                  distance = distance + scattering_factor + 0.007
                elif candidate['floor'] == 6:
                  distance = distance + scattering_factor + 0.008
                elif candidate['floor'] == 7:
                  distance = distance + scattering_factor + 0.009
                elif candidate['floor'] == 8:
                  distance = distance + scattering_factor + 0.010
                elif candidate['floor'] == 9:
                  distance = distance + scattering_factor + 0.011
                elif candidate['floor'] == 10:
                  distance = distance + scattering_factor + 0.012
                elif candidate['floor'] == 11:
                  distance = distance + scattering_factor + 0.013
                elif candidate['floor'] == 12:
                  distance = distance + scattering_factor + 0.014
                elif candidate['floor'] == 13:
                  distance = distance + scattering_factor + 0.015
                elif candidate['floor'] == 14:
                  distance = distance + scattering_factor + 0.016
                else:
                  distance = distance + scattering_factor + 0.017

                if 0 < distance <= max_distance:
                    group.append(candidate)
                    break

Короче говоря: это действительно не работает. В конце я получаю фрейм данных и нахожу людей в тех же местах, которые назначены в ту же группу. Как бы вы это сделали?

1 Ответ

2 голосов
/ 15 марта 2020

Используя ваше решение, добавьте logi c, чтобы увидеть, есть ли человек с такими же координатами в группе. Когда вы проверите, нет ли в группе людей, добавьте. Но если в группе есть человек, для каждого человека в группе рассчитывают расстояние между этим человеком и кандидатом. Если это 0, тогда прервитесь (выйдите и не добавляйте человека в эту группу). Затем go к следующей группе и сделайте то же самое.

Кстати. Я не знаком с этим языком программирования, поэтому, возможно, я написал неверный синтаксис, поэтому, пожалуйста, используйте приведенный выше псевдокод в качестве руководства. Ура!

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 distance == 0 : break;** 

                if candidate['floor'] == -1:                 # consider the floor when calculating the distance 
                  distance = distance + scattering_factor + 0.001
                elif candidate['floor'] == 0:
                  distance = distance + scattering_factor + 0.002
                elif candidate['floor'] == 1:
                  distance = distance + scattering_factor + 0.003
                elif candidate['floor'] == 2:
                  distance = distance + scattering_factor + 0.004
                elif candidate['floor'] == 3:
                  distance = distance + scattering_factor + 0.005
                elif candidate['floor'] == 4:
                  distance = distance + scattering_factor + 0.006
                elif candidate['floor'] == 5:
                  distance = distance + scattering_factor + 0.007
                elif candidate['floor'] == 6:
                  distance = distance + scattering_factor + 0.008
                elif candidate['floor'] == 7:
                  distance = distance + scattering_factor + 0.009
                elif candidate['floor'] == 8:
                  distance = distance + scattering_factor + 0.010
                elif candidate['floor'] == 9:
                  distance = distance + scattering_factor + 0.011
                elif candidate['floor'] == 10:
                  distance = distance + scattering_factor + 0.012
                elif candidate['floor'] == 11:
                  distance = distance + scattering_factor + 0.013
                elif candidate['floor'] == 12:
                  distance = distance + scattering_factor + 0.014
                elif candidate['floor'] == 13:
                  distance = distance + scattering_factor + 0.015
                elif candidate['floor'] == 14:
                  distance = distance + scattering_factor + 0.016
                else:
                  distance = distance + scattering_factor + 0.017

                if 0 < distance <= max_distance:
                    group.append(candidate)
                    break
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...