Разделительная строка, если найден разделитель

1

Рассмотрим следующий фрейм данных,

cols = ['Id', 'col1', 'col2', 'col3']
vals = [('1A','Not his side|:|This side', 'This side', 'Not this either|:|but this'),  
        ('1B','Keep this', 'This one|:|keep this', 'remove|:|keep that')]

dd1 = sqlContext.createDataFrame(vals, cols)

#+---+------------------------+--------------------+--------------------------+
#|Id |col1                    |col2                |col3                      |
#+---+------------------------+--------------------+--------------------------+
#|1A |Not his side|:|This side|This side           |Not this either|:|but this|
#|1B |Keep this               |This one|:|keep this|remove|:|keep that        |
#+---+------------------------+--------------------+--------------------------+

Мне нужно разбить строки на |:| и сохраните второе слово. Однако, если строка не содержит разделителя (|:|), тогда я получаю null, то есть:

users1 = [F.split(F.col(x), "\\|:\\|").alias(x) for x in cols]
dd1.select(*users1).show()

#+---------+---------+---------+
#|     col1|     col2|     col3|
#+---------+---------+---------+
#|This side|     null| but this|
#|     null|keep this|keep that|
#+---------+---------+---------+

Результат, который я ищу, это:

+---+---------+---------+---------+
|Id |col1     |col2     |col3     |
+---+---------+---------+---------+
|1A |This side|This side|but this |
|1B |Keep this|keep this|keep that|
+---+---------+---------+---------+
Теги:
apache-spark
apache-spark-sql
pyspark

3 ответа

2
Лучший ответ

Используйте, when и в otherwise и проверьте, содержит ли строка "|:|" , Это можно сделать следующим образом:

cols = ['col1', 'col2', 'col3']

users1 = [F.when(F.col(x).contains("|:|"), F.split(F.col(x), "\\|:\\|")[1]).otherwise(F.col(x)).alias(x) for x in cols]
dd1.select(F.col('Id'), *users1)

Здесь cols включают только столбцы, которые вы хотите разделить. Окончательный select будет включать столбец Id.

  • 1
    Спасибо. Это будет хорошо. Очень читабельно тоже.
  • 1
    @ Сотош: Нет проблем, рад помочь. Я видел, как вы просили столбец Id, вы можете увидеть выше в ответе, как выбрать его с остальными.
Показать ещё 3 комментария
1

Вы можете использовать, when и size встроенных функций, как

users1 = [F.when(F.size(F.split(F.col(x), "\\|:\\|")) > 1, F.split(F.col(x), "\\|:\\|")[1]).otherwise(F.col(x)).alias(x) for x in cols]
dd1.select(*users1).show()

которые должны дать вам

+---+---------+---------+---------+
| Id|     col1|     col2|     col3|
+---+---------+---------+---------+
| 1A|This side|This side| but this|
| 1B|Keep this|keep this|keep that|
+---+---------+---------+---------+

Вы можете изменить ответ, чтобы использовать функцию split только один раз.

Я надеюсь, что ответ будет полезен и должен быть хорошим советом о том, как действовать.

  • 0
    Это концепция, к которой я стремился, но чего-то не хватало, и я никак не мог туда добраться. Спасибо @Ramesh
  • 0
    Это не дает мне Id . Где вы выбираете это?
Показать ещё 3 комментария
1

Выбор, который вы определили в своих вопросах, не дает результата, о котором вы говорили. Я думаю, вы забыли выбрать элемент из массива;)

users1 = [F.split(F.col(x), "\\|:\\|").alias(x) for x in cols]
dd1.select(*users1).show()
+----+--------------------+--------------------+--------------------+
|  Id|                col1|                col2|                col3|
+----+--------------------+--------------------+--------------------+
|[1A]|[Not his side, Th...|         [This side]|[Not this either,...|
|[1B]|         [Keep this]|[This one, keep t...| [remove, keep that]|
+----+--------------------+--------------------+--------------------+

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

users2 = [F.col(x).getItem(F.size(F.col(x))-1).alias(x) for x in cols]
dd1.select(*users1).select(*users2).show()
+---+---------+---------+---------+
| Id|     col1|     col2|     col3|
+---+---------+---------+---------+
| 1A|This side|This side| but this|
| 1B|Keep this|keep this|keep that|
+---+---------+---------+---------+

Ещё вопросы

Сообщество Overcoder
Наверх
Меню