文章目录
- 1 官方说明
- 2 使用时涉及到的的包
- 3 df.col , df['col'] , col('col')之间的区别
- 3.1 df.col
- 3.2 df['col']
- 3.3 col('col')
1 官方说明
df("columnName") // On a specific DataFrame.
col("columnName") // A generic column no yet associated with a DataFrame.
col("columnName.field") // Extracting a struct field
col("`a.column.with.dots`") // Escape `.` in column names.
expr("a + 1") // A column that is constructed from a parsed SQL Expression.
lit("abc") // A column that produces a literal (constant) value.
$"columnName" // Scala short hand for a named column.
2 使用时涉及到的的包
- on a specific DataFrame.
import org.apache.spark.sql.Column
df("columnName")
- A generic column no yet associated with a DataFrame.
import org.apache.spark.sql.functions._
col("columnName")
- Scala short hand for a named column.
import spark.implicits._
df.select($"name")
- Scala short hand for a named column.
import spark.implicits._
df.select('name)
org.apache.spark.sql.functions
是一个Object,提供了约两百多个函数。大部分函数与Hive的差不多。除UDF函数,均可在spark-sql中直接使用。经过import org.apache.spark.sql.functions._
,也可以用于Dataframe,Dataset。
org.apache.spark.sql.functions导入后可用的函数集合:Spark SQL 函数全集
3 df.col , df[‘col’] , col(‘col’)之间的区别
在大多数实际应用中,都有几乎没有差别。
但是,它们是通过调用不同的基础函数来实现的 (源) ,因此不完全相同。
我们可以举一个小例子来说明:
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 |
#+ ---- + ---- + --------- +
3.1 df.col
这是最不灵活的,只能引用使用。运算符可以访问的有效列。这排除了包含空格或特殊字符的列名以及以整数开头的列名。
此语法调用 df.__getattr __(" col"; )
#返回用name表示的:class:`Column。
print(df .__ getattr __.__ doc__)
>> df.select(df.age).collect()
[行(年龄= 2),行(年龄= 5)]
只能访问其第一列
>>> df.2col
文件"< ipython-input-39-8e82c2dd5b7c>",第1行
df.2col
^
SyntaxError:无效语法
< / code>
3.2 df[‘col’]
这将调用 df.__getitem __
。您具有更大的灵活性,因为您可以做 __ getattr __ 可以做的所有事情,还可以指定任何列名。
# Column< 2col>
df [" 2col"]
再次检查一些条件,在本例中为 pyspark.sql。返回由输入字符串指定的列。
此外,您还可以传入多个列(作为列表或 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
。
最后,您还可以按索引访问列:
#Column<third col>
df[2]
3.3 col(‘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')
).show()
#+----+----+---------+---------+
#| col|2col|third col| new|
#+----+----+---------+---------+
#| 1| a| 0|third col|
#| 2| b| null| col|
#|null| c| 3|third col|
#+----+----+---------+---------+
oops,这不是我的意思。 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'))
).show()
#+----+----+---------+---+
#| col|2col|third col|new|
#+----+----+---------+---+
#| 1| a| 0| 0|
#| 2| b| null| 2|
#|null| c| 3| 3|
#+----+----+---------+---+
因为是col()
,它创建了列表达式而没有检查以下2方面:
- It can be re-used as it’s not df specific - 它可以重复使用不特定于df
- It can be used before the df is assigned - 可以在分配df之前使用
可以理解成它是游离的,类似于一个”series游侠“
age = col('dob') / 365
if_expr = when(age < 18, 'underage').otherwise('adult')
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 generates
Column<b'(dob / 365)'>
- if_expr generates
Column<b'CASE WHEN ((dob / 365) < 18) THEN underage ELSE adult END'>
举例说明
假设有两个表:
- df1 : account_id
- df2 : account_id
# 这里选中的是左表的‘account_id’
df1.join(df2,'account_id','left').select(col('account_id'))
# 等价于写
df1.join(df2,'account_id','left').select(df1.account_id)
# 这里选中的是右表的‘account_id’
df1.join(df2,'account_id','right').select(col('account_id'))
# 等价于写
df1.join(df2,'account_id','right').select(df2.account_id)
# 这里不知道选中谁的时候,体现出了col的牛逼之处
df1.join(df2,'account_id','outer').select(col('account_id'))
总而言之,用col就是很省心
用col吧,大兄弟