(панды) Как я могу создать уникальный идентификатор на основе трех одинаковых столбцов данных, где порядок не имеет значения? - PullRequest
1 голос
/ 17 июня 2019

(Python / Pandas) Я делаю некоторый анализ данных по ценам на жилье в Великобритании, чтобы выяснить, соответствуют ли цены на жилье качеству близлежащих школ.Я сопоставил URN (уникальный ссылочный номер) трех ближайших школ с каждой транзакцией цены дома. Это столбцы URN_1, URN_2, URN_3 в данных.

Я хотел бы оценить модель фиксированных эффектов на данных, где фиксированные эффекты основаны на трех ближайших школах.Поэтому я хочу создать уникальный идентификатор для каждого кластера из трех школ, и я хочу, чтобы это не зависело от порядка школ. Например, свойство A и свойство B должны иметь одинаковые идентификаторы, несмотря на разный порядок школ.

Property    URN_1   URN_2   URN_3
A         100053   100052   100054
B         100052   100054   100053

Кто-нибудь знает, как я создаю уникальные идентификаторы кластера с использованием Python?

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

Вот что я пробовал:

import pandas as pd
URN1=[1,2,3,4,5]
URN2=[5,4,3,2,1]
URN3=[1,2,3,2,1]
lst=['a','b','c','d','e']
df=pd.DataFrame(list(zip(URN1,URN2,URN3)),
columns['URN_1','URN_2','URN_3'],index=lst)
df['clusterid']=df.groupby(['URN_1','URN_2','URN_3']).ngroup()
print(df)

Я бы хотел, чтобы наблюдения 'a' и 'e' имели одинаковые идентификаторы кластера, но они дают разные идентификаторыспособ.

Ответы [ 3 ]

1 голос
/ 17 июня 2019

Это работает, если ваши данные не слишком длинные:

# we sort the values of each row
# and turn them to tuples
markers = (df[['URN_1','URN_2','URN_3']]
             .apply(lambda x: tuple(sorted(x.values)), axis=1)
          )

df['clisterid'] = df.groupby(markers).ngroup()

Выход:

  Property   URN_1   URN_2   URN_3  clisterid
0        A  100053  100052  100054          0
1        B  100052  100054  100053          0

Вариант 2: , так как в приведенном выше решении используется apply, что в некоторых случаях может быть не идеальным. Вот небольшой математический трюк: известно, что группа (a,b,c) однозначно (с точностью до перестановки) определяется (a+b+c, a**2+b**2+c**2, abc). Таким образом, мы можем вычислить эти значения и сгруппировать по ним:

tmp_df = df[['URN_1','URN_2','URN_3']]

s = tmp_df.sum(1)         # sums
sq = (tmp_df**2).sum(1)   # sum of squares
p = tmp_df.prod(1)        # products

# groupby
df['clisterid'] = df.groupby([s,sq,p]).ngroup()

Производительность : первый подход занимает 14 секунд для обработки 2 миллионов строк, а второй - менее 1 секунды.

0 голосов
/ 17 июня 2019

Вы можете создать строку для каждого, используя отсортированные 3 URN.
Затем сгруппировать по этой новой переменной и использовать ngroup (), как вы пытались до этого

df['URN_join'] = df[['URN_1','URN_2','URN_3']].apply(lambda x: '_'.join([str(nb) for nb in sorted(x)]), axis=1)
df['clusterid'] = df.groupby(['URN_join']).ngroup()
df

Вывод:

    URN_1   URN_2   URN_3   clusterid   URN_join
a   1       5       1       0           1_1_5
b   2       4       2       1           2_2_4
c   3       3       3       2           3_3_3
d   4       2       2       1           2_2_4
e   5       1       1       0           1_1_5
0 голосов
/ 17 июня 2019

Используйте factorize для уникального строкового объекта комбинаций. Поскольку порядок не имеет значения, мы сначала сортируем его и объединяем.

df['clusterid'] = pd.factorize(df[['URN_1','URN_2','URN_3']].apply(lambda x: ','.join([str(y) for y in sorted(x)]),1))[0]

Выход:

       URN_1  URN_2  URN_3  clusterid  clisterid
a      1      5      1          0          0
b      2      4      2          1          1
c      3      3      3          2          2
d      4      2      2          3          1
e      5      1      1          4          0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...