Ссылка на столбец PySpark DataFrame: df.col против df ['col'] против F.col ('col')? - PullRequest
2 голосов
/ 11 марта 2019

У меня есть понятие, я надеюсь, вы можете помочь уточнить:

В чем разница между следующими тремя способами ссылки на столбец в кадре данных PySpark. Я знаю, что в разных ситуациях нужны разные формы, но не знаю, почему.

  1. df.col : например, F.count(df.col)
  2. df ['col'] : например, df['col'] == 0
  3. F.col ('col') : например, df.filter(F.col('col').isNull())

Большое спасибо!

1 Ответ

3 голосов
/ 11 марта 2019

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

Мы можем проиллюстрировать небольшой пример:

df = spark.createDataFrame(
    [(1,'a', 0), (2,'b',None), (None,'c',3)], 
    ['col', '2col', 'third col']
)

df.show()
#+----+----+---------+
#| col|2col|third col|
#+----+----+---------+
#|   1|   a|        0|
#|   2|   b|     null|
#|null|   c|        3|
#+----+----+---------+

1. df.col

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

Этот синтаксис вызывает df.__getattr__("col").

print(df.__getattr__.__doc__)
#Returns the :class:`Column` denoted by ``name``.
#
#        >>> df.select(df.age).collect()
#        [Row(age=2), Row(age=5)]
#
#        .. versionadded:: 1.3

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

>>> df.2col
  File "<ipython-input-39-8e82c2dd5b7c>", line 1
    df.2col
       ^
SyntaxError: invalid syntax

Под капотом он проверяет, содержится ли имя столбца в df.columns, а затем возвращает указанное pyspark.sql.Column.

2. df["col"]

Позвонит на df.__getitem__. У вас есть больше гибкости в том, что вы можете делать все, что может делать __getattr__, плюс вы можете указать любое имя столбца.

df["2col"]
#Column<2col> 

Еще раз, под капотом проверяются некоторые условия, и в этом случае возвращается pyspark.sql.Column, указанный во входной строке.

Кроме того, вы можете передать несколько столбцов (как list или tuple) или выражения столбцов.

from pyspark.sql.functions import expr
df[['col', expr('`third col` IS NULL')]].show()
#+----+-------------------+
#| col|(third col IS NULL)|
#+----+-------------------+
#|   1|              false|
#|   2|               true|
#|null|              false|
#+----+-------------------+

Обратите внимание, что в случае нескольких столбцов __getitem__ просто вызывает pyspark.sql.DataFrame.select.

Наконец, вы также можете получить доступ к столбцам по индексу:

df[2]
#Column<third col>

3. pyspark.sql.functions.col

Возвращает Column на основе заданного имени. Это полезное сокращение, когда вам нужно указать, что вы хотите столбец, а не строковый литерал.

Например, предположим, что мы хотим создать новый столбец, который будет принимать либо значение из "col", либо "third col" на основе значения "2col":

from pyspark.sql.functions import when

df.withColumn(
    'new', 
    f.when(df['2col'].isin(['a', 'c']), 'third col').otherwise('col')
).show()
#+----+----+---------+---------+
#| col|2col|third col|      new|
#+----+----+---------+---------+
#|   1|   a|        0|third col|
#|   2|   b|     null|      col|
#|null|   c|        3|third col|
#+----+----+---------+---------+

Упс, я не это имел ввиду. Спарк подумал, что мне нужны буквальные строки "col" и "third col". Вместо этого я должен был написать:

from pyspark.sql.functions import col
df.withColumn(
    'new', 
    when(df['2col'].isin(['a', 'c']), col('third col')).otherwise(col('col'))
).show()
#+----+----+---------+---+
#| col|2col|third col|new|
#+----+----+---------+---+
#|   1|   a|        0|  0|
#|   2|   b|     null|  2|
#|null|   c|        3|  3|
#+----+----+---------+---+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...