Как вычесть каждую строку в кадрах искровых данных из каждой другой строки в pyspark? - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть искровой фрейм данных с 3 столбцами, которые указывают положения атомов. I-e Положение X, Y и Z. Теперь, чтобы найти расстояние между каждыми 2 атомами, для которого мне нужно применить формулу расстояния. Формула расстояния имеет вид d = sqrt ((x2 − x1) ^ 2 + (y2 − y1) ^ 2 + (z2-z1) ^ 2)

так, чтобы применить приведенную выше формулу, мне нужно вычесть каждую строку в x из каждой другой строки в x, каждую строку в y из любой другой строки в y и т. Д. и затем примените вышеуказанную формулу для каждых двух атомов.

Я пытался создать пользовательскую функцию (udf), но я не могу передать в нее весь фрейм искровых данных, я могу передать только каждый столбец отдельно, а не весь фрейм данных. Из-за чего я не мог перебрать весь фрейм данных, я должен подать заявку на циклы в каждом столбце. В приведенном ниже фрагменте кода показана итерация, которую я выполняю только для Position_X.

@udf
def Distance(Position_X,Position_Y, Position_Z):
    try:
       for x,z in enumerate(Position_X) :
           firstAtom = z
           for y, a in enumerate(Position_X):
                if (x!=y):
                    diff = firstAtom - a
           return diff
    except:
        return None

newDF1 = atomsDF.withColumn("Distance", Distance(*atomsDF.columns))

My atomDF spark dataframe look like this, each row shows the x,y,z coordinates of one atom in space. Right now we are taking only 10 atoms.

Position_X|Position_Y|Position_Z|
+----------+----------+----------+
|    27.545|     6.743|    12.111|
|    27.708|     7.543|    13.332|
|    27.640|     9.039|    12.970|
|    26.991|     9.793|    13.693|
|    29.016|     7.166|    14.106|
|    29.286|     8.104|    15.273|
|    28.977|     5.725|    14.603|
|    28.267|     9.456|    11.844|
|    28.290|    10.849|    11.372|
|    26.869|    11.393|    11.161|
+----------+----------+----------+

Как мне решить вышеуказанную проблему в pyspark i-e. Как вычесть каждый ряд из каждого другого ряда? Как передать весь искровой фрейм данных в udf, а не в его столбцы? И как избежать использования слишком много для циклов?

Ожидаемый результат для каждых двух атомов (рядов) будет расстоянием между двумя строками, рассчитанным по приведенной выше формуле расстояния. Мне не нужно сохранять это расстояние, потому что я буду использовать другую формулу Потенциальной энергии. Или, если это можно сохранить в отдельном кадре данных, я не против.

1 Ответ

1 голос
/ 03 апреля 2019

Если вы хотите сравнить 2 на 2 атома (линии), которые вам нужны для перекрестного соединения ... что не рекомендуется.

Вы можете использовать функцию monotonically_increasing_id для генерации идентификатора для каждой строки.

from pyspark.sql import functions as F
df = df.withColumn("id", F.monotonically_increasing_id())

Затем вы пересекаете свой фрейм данных и фильтруете строку, где "id_1> id_2"

df_1 = df.select(*(F.col(col).alias("{}_1".format(col)) for col in df.columns))
df_2 = df.select(*(F.col(col).alias("{}_2".format(col)) for col in df.columns))
df_3 = df_1.crossJoin(df_2).where("id_1 > id_2")

df_3 содержит 45 необходимых вам строк.Вам просто нужно применить свою формулу:

df_4 = df_3.withColumn(
    "distance",
    F.sqrt(
        F.pow(F.col("Position_X_1") - F.col("Position_X_2"), F.lit(2))
        + F.pow(F.col("Position_Y_1") - F.col("Position_Y_2"), F.lit(2))
        + F.pow(F.col("Position_Z_1") - F.col("Position_Z_2"), F.lit(2))
    )
)


df_4.orderBy('id_2', 'id_1').show()
+------------+------------+------------+----------+------------+------------+------------+----+------------------+
|Position_X_1|Position_Y_1|Position_Z_1|      id_1|Position_X_2|Position_Y_2|Position_Z_2|id_2|          distance|
+------------+------------+------------+----------+------------+------------+------------+----+------------------+
|      27.708|       7.543|      13.332|         1|      27.545|       6.743|      12.111|   0|1.4688124454810418|
|       27.64|       9.039|       12.97|         2|      27.545|       6.743|      12.111|   0| 2.453267616873462|
|      26.991|       9.793|      13.693|         3|      27.545|       6.743|      12.111|   0| 3.480249991020759|
|      29.016|       7.166|      14.106|         4|      27.545|       6.743|      12.111|   0|2.5145168522004355|
|      29.286|       8.104|      15.273|8589934592|      27.545|       6.743|      12.111|   0|3.8576736513085175|
|      28.977|       5.725|      14.603|8589934593|      27.545|       6.743|      12.111|   0| 3.049100195139542|
|      28.267|       9.456|      11.844|8589934594|      27.545|       6.743|      12.111|   0|2.8200960976534106|
|       28.29|      10.849|      11.372|8589934595|      27.545|       6.743|      12.111|   0| 4.237969089080287|
|      26.869|      11.393|      11.161|8589934596|      27.545|       6.743|      12.111|   0| 4.793952023122468|
|       27.64|       9.039|       12.97|         2|      27.708|       7.543|      13.332|   1|1.5406764747993003|
|      26.991|       9.793|      13.693|         3|      27.708|       7.543|      13.332|   1|2.3889139791964036|
|      29.016|       7.166|      14.106|         4|      27.708|       7.543|      13.332|   1|1.5659083625806454|
|      29.286|       8.104|      15.273|8589934592|      27.708|       7.543|      13.332|   1|2.5636470115833037|
|      28.977|       5.725|      14.603|8589934593|      27.708|       7.543|      13.332|   1|2.5555676473143896|
|      28.267|       9.456|      11.844|8589934594|      27.708|       7.543|      13.332|   1|  2.48720606303539|
|       28.29|      10.849|      11.372|8589934595|      27.708|       7.543|      13.332|   1|  3.88715319996524|
|      26.869|      11.393|      11.161|8589934596|      27.708|       7.543|      13.332|   1| 4.498851186691999|
|      26.991|       9.793|      13.693|         3|       27.64|       9.039|       12.97|   2|1.2298154333069653|
|      29.016|       7.166|      14.106|         4|       27.64|       9.039|       12.97|   2|2.5868902180030737|
|      29.286|       8.104|      15.273|8589934592|       27.64|       9.039|       12.97|   2|2.9811658793163454|
+------------+------------+------------+----------+------------+------------+------------+----+------------------+
only showing top 20 rows

Она работает для небольшого количества данных, но с большим количеством crossJoin уничтожит исполнения.

...