首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PySpark DataFrame列引用: df.col vs. df['col'] vs. F.col('col')?

PySpark DataFrame列引用: df.col vs. df['col'] vs. F.col('col')?
EN

Stack Overflow用户
提问于 2019-03-11 15:32:48
回答 1查看 15.4K关注 0票数 23

我有一个概念,我希望你能帮助澄清:

以下三种引用PySpark数据格式中列的方法有什么区别。我知道不同的情况需要不同的形式,但不知道为什么。

  1. df.col:例如F.count(df.col)
  2. df‘’col‘:例如df['col'] == 0
  3. F.col('col'):(例如df.filter(F.col('col').isNull()) )

非常感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-11 16:37:34

在大多数实际应用中,几乎没有区别。但是,它们是通过调用不同的底层函数(来源)来实现的,因此它们并不完全相同。

我们可以用一个小例子来说明:

代码语言:javascript
运行
复制
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")

代码语言:javascript
运行
复制
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

使用.语法,只能访问本示例的第一列dataframe。

代码语言:javascript
运行
复制
>>> 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__所能做的所有事情,并且可以指定任何列名。

代码语言:javascript
运行
复制
df["2col"]
#Column<2col> 

再次,在掩码下检查一些条件,在本例中,返回输入字符串指定的pyspark.sql.Column

此外,还可以传入多个列(作为listtuple)或列表达式。

代码语言:javascript
运行
复制
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

最后,还可以按索引访问列:

代码语言:javascript
运行
复制
df[2]
#Column<third col>

3. pyspark.sql.functions.col

这是选择列的本机方式,并返回一个expression (所有列函数都是这样),它根据给定的名称选择列。当您需要指定一个列而不是字符串文本时,这是非常有用的速记。

例如,假设我们想要创建一个新列,它将根据"col""third col"的值接受"2col"的值。

代码语言:javascript
运行
复制
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"。相反,我应该写的是:

代码语言:javascript
运行
复制
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|
#+----+----+---------+---+

因为is col()在不检查的情况下创建列表达式,因此有两个有趣的副作用。

  1. 它可以被重复使用,因为它不是df特定的
  2. 它可以在指定df之前使用。
代码语言:javascript
运行
复制
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生成Column<b'(dob / 365)'>

if_expr生成Column<b'CASE WHEN ((dob / 365) < 18) THEN underage ELSE adult END'>

票数 34
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55105363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档