Создание нового фрейма данных с манхэттенским расстоянием в python

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

x_train :
index a b c
11    2 5 7
23    4 2 0
312   2 2 2
x_test : 
index a b c
22    1 1 1
30    2 0 0

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

dist_dataframe:
index 11 23 312
22    11 5  3
30    12 4  4

а у меня сейчас вот это:

def manhattan_distance(a, b):
    return sum(abs(e1-e2) for e1, e2 in zip(a,b))

def calc_distance(X_test,X_train):
    dist_dataframe = pd.DataFrame(index=X_test.index,columns = X_train.index)
    for i in X_train.index:
        for j in X_test.index:
            dist_dataframe.loc[i,j]=manhattan_distance(X_train.loc[[i]],X_test.loc[[j]])
    return dist_dataframe

что я получаю из кода, который у меня есть, это этот фрейм данных:

dist_dataframe:
index
index 11  23  312
22    NaN NaN NaN
30    NaN NaN NaN

Я получаю правильный размер фрейма данных, за исключением того, что у него есть 2 строки, называемые индексами, которые я получаю при создании нового фрейма данных, а также я получаю сообщение об ошибке независимо от того, что я делаю в строке расчета Манхэттена, может ли кто-нибудь помочь мне здесь, пожалуйста?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
787
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в вашем коде

В вашем коде есть очень небольшая проблема, то есть доступ к значениям в dist_dataframe. Итак, вместо dist_dataframe.loc[i,j] вы должны поменять порядок i и j и сделать его похожим на dist_dataframe.loc[j,i]

Более эффективное решение

Это будет работать нормально, но, поскольку вы новый участник, я также хотел бы отметить эффективность вашего кода. Всегда старайтесь заменить циклы встроенными функциями pandas. Поскольку они написаны на C, это делает их намного быстрее. Итак, вот более эффективное решение:

def manhattan_distance(a, b):
    return sum(abs(e1-e2) for e1, e2 in zip(a,b))

def xtrain_distance(row):
    distances = {}
    for i,each in x_train.iterrows():
        distances[i] = manhattan_distance(each,row)
    return distances

result = x_test.apply(xtrain_distance, axis=1)

# converting into dataframe
pd.DataFrame(dict(result)).transpose()

Он также выдает тот же результат, что и в вашем примере, и вы не видите разницы во времени. Но при запуске на большем размере (те же данные масштабируются более чем в 20 раз), то есть 60 x_train сэмплов и 40 x_test сэмплов, вот разница во времени:

Ваше решение заняло: 929 ms

Это решение заняло: 207 ms

Он стал в 4 раза быстрее, просто убрав один цикл for. Обратите внимание, что его можно сделать более эффективным, но для демонстрации я использовал это решение.

Спасибо, это сработало. Я проголосовал, но это не отображается :/. Также спасибо за совет по эффективному решению! но я не уверен, что смогу использовать его для своего задания, поскольку нам не разрешалось использовать какую-либо функцию, которая выполняет какую-либо из функций векторного расстояния, не уверен, что ваше решение использует что-либо, но был бы рад узнать

bendush 22.12.2020 00:47

Привет @bendush, решение не использует никаких функций, связанных с векторизацией. Он использует только метод применения в пандах, который, проще говоря, эффективно перебирает фрейм данных по любой оси, обрабатывает функцию для каждого элемента и, следовательно, дает выходной фрейм данных. Чтобы лучше понять и сравнить методы векторизации, обратитесь сюда: engineering.upside.com/…

Prashant Gupta 22.12.2020 01:06

Спасибо! Я не понял, что такое строка переменной, которую вы получаете в xtrain_distance, если вы можете объяснить это, я был бы признателен!

bendush 22.12.2020 12:43

Конечно. Когда вы используете атрибут применения в пандах, он принимает имя функции в качестве аргумента. И затем он передает каждую строку (если ось = 1) или столбец (если ось = 0) кадра данных этой функции в качестве входных данных. В нашем случае все строки фрейма данных x_test передаются функции одна за другой, и на выходе получается серия ответов функции pandas.

Prashant Gupta 22.12.2020 15:13

Другие вопросы по теме