我有一个概念,我希望你能帮助澄清:
在 PySpark 数据框中引用列的以下三种方式有什么区别。我知道不同的情况需要不同的形式,但不知道为什么。
df.col:e.g.F.count(df.col)
df['col']:e.g.
df['col'] ==0
F.col('col'):e.g.
df.filter(F.col('col').isNull())
非常感谢!
在大多数实际应用中,几乎没有区别。但是,它们是通过调用不同的底层函数(source)来实现的,因此并不完全相同。
我们可以用一个小例子来说明:
df = spark.createDataFrame(
[(1,'a', 0), (2,'b',None), (None,'c',3)],
['col', '2col', 'third col']
)
df.sw()
#+----+----+---------+
#| 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 :cl:`Column` denoted by ``name``.
#
# >>> df.select(df.age).collect()
# [Row(age=2), Row(age=5)]
#
# .. versionadded:: 1.3
使用.
语法,您只能访问此示例数据帧的第一列。
>>> df.2col
File "<ipytn-input-39-8e82c2dd5b7c>", line 1
df.2col
^
SyntaxError: invalid syntax
在引擎盖下,它检查列名是否包含在df.columns
中,然后返回指定的pyspark.sql.Column
。
df["col"]
这将调用df.__geem__
。您可以更灵活地执行__getattr__
可以执行的所有操作,还可以指定任何列名。
df["2col"]
#Column<2col>
再一次,在引擎盖下检查一些条件,在这种情况下,返回由输入字符串指定的pyspark.sql.Column
。
此外,您可以传入多个列(如list
或tuple
)或列表达式。
from pyspark.sql.functions import expr
df[['col', expr('`third col` IS NULL')]].sw()
#+----+-------------------+
#| col|(third col IS NULL)|
#+----+-------------------+
#| 1| false|
#| 2| true|
#|null| false|
#+----+-------------------+
请注意,在多列的情况下,__geem__
只是调用pyspark.sql.DataFrame.select
。
最后,您还可以按索引访问列:
df[2]
#Column<third col>
3.pyspark.sql.functions.col
这是 Spark 本机选择列的方式,并返回一个expression
(这是所有列函数的情况),它根据给定的名称选择列。当您需要指定您想要的列而不是字符串文字时,这是有用的速记。
例如,假设我们想要创建一个新列,该列将根据"2col"
的值接受"col"
或"third col"
的值:
from pyspark.sql.functions import when
df.withColumn(
'new',
f.when(df['2col'].isin(['a', 'c']), 'third col').otherwise('col')
).sw()
#+----+----+---------+---------+
#| col|2col|third col| new|
#+----+----+---------+---------+
#| 1| a| 0|third col|
#| 2| b| null| col|
#|null| c| 3|third col|
#+----+----+---------+---------+
哎呀,这不是我的意思。Spark 认为我想要字面字符串"col"
和"third col"
。相反,我应该写的是:
from pyspark.sql.functions import col
df.withColumn(
'new',
when(df['2col'].isin(['a', 'c']), col('third col')).otherwise(col('col'))
).sw()
#+----+----+---------+---+
#| col|2col|third col|new|
#+----+----+---------+---+
#| 1| a| 0| 0|
#| 2| b| null| 2|
#|null| c| 3| 3|
#+----+----+---------+---+
因为是 col()创建列表达式而不检查有两个有趣的副作用。
它可以重复使用,因为它不是 df 特定的
它可以在分配 df 之前使用
age = col('dob') / 365
if_expr = when(age < 18, 'underage').otherwise('')
df1 = df.read.csv(path).withColumn('age_category', if_expr)
df2 = df.read.parquet(path)\
.select('*', age.alias('age'), if_expr.alias('age_category'))
age
generatesColumn<b'(dob / 365)'>
if_expr
generatesColumn<b'CASE WHEN ((dob / 365) <18) THEN underage ELSE END'>
本站系公益性非盈利分享网址,本文来自用户投稿,不代表边看边学立场,如若转载,请注明出处
评论列表(54条)