Панды определяют строки, в которых два столбца имеют одинаковые строки

avatar
bluetooth
1 июля 2021 в 18:48
101
4
3

Формулировка вопроса может сбивать с толку, но в следующем фрейме данных я хотел бы иметь возможность выбрать первую и последнюю строку:

dt = [['BOS','SF'],['SF','LA'],['LA','NYC'],['SF','BOS'],
      ]
my_df= pd.DataFrame(columns = ['Source','destination'], data = dt)
my_df

Другими словами, определите пары строк, где назначение первой строки является источником другой и наоборот.

Похоже на простую задачу, но я не могу найти никакого решения.

Источник
Mustafa Aydın
1 июля 2021 в 19:11
1

привет, что если есть еще одна строка с ["BOS", "SF"], что должно произойти с ней и конечным результатом?

bluetooth
2 июля 2021 в 04:37
0

@MustafaAydın, я бы удалил эту строку методом .drop_duplicates().

Mustafa Aydın
2 июля 2021 в 05:38
0

Понятно, спасибо за разъяснение; Я написал ответ и теперь восстановил его, надеюсь, это поможет.

Ответы (4)

avatar
Mustafa Aydın
1 июля 2021 в 18:57
1

Одним из способов игнорировать порядок между двумя столбцами является сортировка каждой строки внутри себя, что может сделать np.sort. Затем вы можете сформировать новый кадр данных с этими упорядоченными строками. duplicated с keep=False пометит все повторяющиеся строки как True, которые мы можем использовать в качестве маски для индексации исходного фрейма данных:

rows_sorted_df = pd.DataFrame(np.sort(df))
dups = rows_sorted_df.duplicated(keep=False)
result = df[dups]

чтобы получить

>>> rows_sorted_df

     0    1
0  BOS   SF
1   LA   SF
2   LA  NYC
3  BOS   SF

>>> dups

0     True
1    False
2    False
3     True

>>> result

  Source destination
0    BOS          SF
3     SF         BOS
avatar
bpgeck
1 июля 2021 в 23:23
0

IMO, лучший способ сделать это — использовать join следующим образом:

import pandas as pd

dt = [
  ['BOS','SF'],
  ['SF','LA'],
  ['LA','NYC'],
  ['SF','BOS'],
]

my_df = pd.DataFrame(columns = ['Source','destination'], data = dt)
source_df = my_df.set_index('Source')
dest_df = my_df.set_index('destination')
joined_df = source_df.join(dest_df)

print(joined_df)

Это вывод (сначала немного запутанный):

    destination Source
BOS          SF     SF
LA          NYC     SF
SF           LA    BOS
SF          BOS    BOS

Если мы подумаем об этом немного глубже, это обретет смысл. Возьмем эти строки из ввода:

  ['SF','LA'],
  ['LA','NYC'],

Наше объединение превращает эти строки в "источник -> средний -> пункт назначения" или "SF -> LA -> NYC". Глядя на нашу результирующую таблицу

    destination Source
LA          NYC     SF

Мы можем прочитать это как «От исходного столбца« SF »к целевому столбцу« NYC »через индекс строки« LA ». Если вы хотите, чтобы фрейм данных был более читабельным, вы можете добавить следующее :

joined_df.index.name = 'middle'
joined_df = joined_df.reset_index()
print(joined_df)
avatar
Pedro Angelini
1 июля 2021 в 22:41
0

Вот к чему я пришел, думая о соединениях.

    import pandas as pd
    dt = [['BOS', 'SF'], ['SF', 'LA'], ['LA', 'NYC'], ['SF', 'BOS'],
          ]
    df = pd.DataFrame(columns=['Source', 'destination'], data=dt)
    df
Источник пункт назначения
0 ЛС SF
1 SF ЛА
2 ЛА Нью-Йорк
3 SF ЛС

вычислить совпадения между адресатом -> источником

    left = df.copy()
    right = df.copy().set_index("Source")
    
    dest_to_source = left.join(right, on=[left["destination"]], 
    lsuffix='_original', rsuffix="_matched", how="inner")
    # pandas joins do weird things to the column names, so renaming and reordering
    dest_to_source.columns = ["Source_matched","Source_original","destination_original","destination_matched"]
    dest_to_source = dest_to_source[["Source_original","destination_original","Source_matched","destination_matched"]]
    dest_to_source

и вот результат:

Источник_оригинал destination_original Source_matched destination_matched
0 ЛС SF SF ЛС
1 SF ЛА ЛА СФ
2 ЛА Нью-Йорк Нью-Йорк ЛА
3 SF ЛС ЛС SF

затем вы можете сделать то же самое для источника -> пункта назначения (для части вопроса "наоборот")\

    right = df.copy().set_index("destination")
    source_to_dest = left.join(right, on=[left["Source"]], lsuffix='_original',rsuffix='_matched', how="inner")
    source_to_dest.columns = ["destination_matched","Source_original","destination_original","Source_matched"]
    source_to_dest = source_to_dest[["Source_matched","destination_matched","Source_original","destination_original"]]
    source_to_dest
Source_matched destination_matched Источник_оригинал destination_original
0 SF ЛС ЛС SF
1 ЛС SF SF ЛА
3 ЛС SF SF ЛС
2 SF ЛА ЛА Нью-Йорк
avatar
JJL
1 июля 2021 в 19:08
0

Если вы разделите свои столбцы на отдельные кадры данных, вы можете затем объединить их, чтобы получить только совпадающие строки.

(В этом примере я переименовал столбец в 'code' в каждом df; в качестве альтернативы вы можете указать аргументы right_on и left_on в вызове merge.)

s = my_df['Source'].reset_index().rename(columns={'Source':'code', 'index':'source_index'})
d = my_df['destination'].reset_index().rename(columns={'destination':'code', 'index':'dest_index'})

sd = pd.merge(s, d)


In: sd
Out: 
   source_index code  dest_index
0             0  BOS           3
1             1   SF           0
2             3   SF           0
3             2   LA           1