【Python笔记】Spark获取DataFrame中列的方式--col,$,column,apply

本文详细介绍了Apache Spark中处理DataFrame和Dataset时不同列引用方法的区别,包括df.col、df['col']及col('col')的使用场景和注意事项,并通过实例展示了它们在实际应用中的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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 使用时涉及到的的包

  1. on a specific DataFrame.
import org.apache.spark.sql.Column
df("columnName") 
  1. A generic column no yet associated with a DataFrame.
import org.apache.spark.sql.functions._
col("columnName")
  1. Scala short hand for a named column.
import spark.implicits._
df.select($"name")
  1. 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'>

https://stackoverflow.com/questions/55105363/pyspark-dataframe-column-reference-df-col-vs-dfcol-vs-f-colcol


举例说明

假设有两个表:

  • 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吧,大兄弟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值