Как найти не однозначные комбинации в фрейме данных pandas

#python #pandas

#python #pandas

Вопрос:

У меня есть следующий фрейм данных

  bootstrap  cluster_main    cluster_b   distance
    1   0   Cluster 0   Cluster 1   0.002016
    15  0   Cluster 0   Cluster 3   0.001282
    4   0   Cluster 1   Cluster 0   0.000772
    10  0   Cluster 2   Cluster 2   0.000990
    26  1   Cluster 0   Cluster 2   0.001034
    16  1   Cluster 2   Cluster 0   0.000159
    31  1   Cluster 3   Cluster 3   0.000889
    21  1   Cluster 1   Cluster 1   0.000961
    35  2   Cluster 0   Cluster 3   0.099427
    36  2   Cluster 1   Cluster 0   0.067036
    43  2   Cluster 2   Cluster 3   0.102834
    45  2   Cluster 3   Cluster 1   0.069814
  

Я хотел бы найти bootstrap s, для которых нет однозначного соответствия между cluster_main и cluster_b .

В приведенном выше примере вывод должен быть 2 and 0 , поскольку Cluster 3 в cluster_b столбце for bootstrap 2 «сопоставляется» дважды, и то же самое происходит Cluster 0 в cluster_main столбце for bootstrap 0

Комментарии:

1. Outut — это не 2 m, потому что in 10 0 Cluster 2 Cluster 2 0.000990 ? Есть совпадение Cluster 2

2. выводится bootstrap число, а не номер кластера. Другими словами, для каждой начальной загрузки, если нет однозначного соответствия cluster_main to cluster_b , я хотел бы получить номер начальной загрузки. Под «один к одному» я подразумеваю, что ни один кластер из cluster_main не сопоставляется дважды с кластером из cluster_b , и наоборот

3. Возможно ли также сказать, что нужен тест, если все значения cluster_b совпадают с cluster_b per bootstrap , а это не так, получить эти значения? Ответ был отредактирован.

4. Я думаю, что логика может быть: для каждого bootstrap cluster_main и cluster_b должно иметь 4 уникальных значения, в противном случае показывать bootstrap число

5. Ответ был отредактирован для сравнения отсортированных значений столбца или наборов

Ответ №1:

Я считаю, что вам нужно:

 #compared sorted values
#f = lambda x: sorted(x['cluster_main']) == sorted(x['cluster_b'])
#comppred sets
#f = lambda x: set(x['cluster_main']) == set(x['cluster_b'])
m = df.groupby('bootstrap').apply(f)
print (m)
bootstrap
0    False
1     True
2    False
dtype: bool
bootstrap
0    False
1     True
2    False
dtype: bool

out = m.index[~m]
print (out)
Int64Index([0, 2], dtype='int64', name='bootstrap')
  

РЕДАКТИРОВАТЬ: я понял, что первое решение было таким же, как наборы comopared, поэтому удалено.

Здесь можно увидеть разницу:

 print (df)
    bootstrap cluster_main  cluster_b  distance
1           0    Cluster 0  Cluster 1  0.002016
15          0    Cluster 0  Cluster 1  0.001282
4           0    Cluster 1  Cluster 0  0.000772
10          0    Cluster 2  Cluster 2  0.000990
26          1    Cluster 2  Cluster 0  0.001034
16          1    Cluster 0  Cluster 2  0.000159
31          1    Cluster 3  Cluster 3  0.000889
21          1    Cluster 1  Cluster 1  0.000961
35          2    Cluster 0  Cluster 0  0.099427
36          2    Cluster 2  Cluster 2  0.067036
43          2    Cluster 2  Cluster 3  0.102834
45          2    Cluster 3  Cluster 2  0.069814


#compared sorted values
f = lambda x: sorted(x['cluster_main']) == sorted(x['cluster_b'])
m = df.groupby('bootstrap').apply(f)
print (m)
bootstrap
0    False
1     True
2     True
dtype: bool

f = lambda x: set(x['cluster_main']) == set(x['cluster_b'])
m = df.groupby('bootstrap').apply(f)
print (m)
bootstrap
0    True
1    True
2    True
dtype: bool
  

Комментарии:

1. Я не думаю, что это сработает. Я немного отредактировал ввод df, но вывод должен быть снова [0,2], где, как указано в приведенном выше коде, будет [0,1,2]

2. Я не понимаю разницы между двумя подходами, если честно

3. @quant — я меняю данные, чтобы объяснить это

4. @quant — добавлена выборка ata, вы можете это проверить?

5. Я проверил это и в моем полном наборе данных. Это работает как шарм, и логика мне понятна, действительно, сортировка — это путь