如何在PySpark中获取数据框列的名称?

81
在pandas中,可以通过column.name来实现。
但是当它是Spark dataframe的列时,该怎么做呢?
例如,调用程序有一个Spark dataframe:spark_df
>>> spark_df.columns
['admit', 'gre', 'gpa', 'rank']

这个程序调用了我的函数:my_function(spark_df['rank'])
my_function中,我需要列的名称,即'rank'
如果是pandas dataframe,我们可以使用以下代码:
>>> pandas_df['rank'].name
'rank'
8个回答

118
您可以通过以下方式从模式中获取名称:

您可以通过以下方式从模式中获取名称:

spark_df.schema.names

打印模式可以帮助你将其可视化

spark_df.printSchema()

6
我想知道的是作为我的函数输入参数的列的名称。 调用程序将通过 my_function(spark_df['rank']) 调用该函数。在 my_function 函数内,我该如何知道传递的列的名称? - Kaushik Acharya
您可以使用 pyspark.sql.functions.col 按名称访问列。例如,df.filter(col(var_name) > 1) - shuaiyuancn
1
@ShuaiYuan, 那不是我想要的。在my_function(col)函数内,我如何知道列名?通过my_function(spark_df['rank'])调用函数。 在my_function内部,我想从输入参数col中提取'rank'作为列名。 - Kaushik Acharya
1
你可以将你的函数改为 myfunc(df, name),这样你就可以在函数中访问 name。当你需要在数据框中使用该列时,可以使用 df[name] - shuaiyuancn
1
或者,您可以利用Dataframe.Column.__repr__ - shuaiyuancn
显示剩余2条评论

26

唯一的方法是进入JVM的底层。

df.col._jc.toString().encode('utf8')

这也是在pyspark代码中将其转换为str的方式。

来自pyspark/sql/column.py:

def __repr__(self):
    return 'Column<%s>' % self._jc.toString().encode('utf8')

3
很不幸,如果存在别名,这将无法提取出来。 - santon
1
True。但是如果有别名,您可以轻松地解析出来。re.search('AS (\S*)', col.alias('some_alias')._jc.toString()).group(1) -> 'some_alias'。当然,这并不完美,因为我们正在进行一些正则表达式解析,但我希望您不太可能在其中有一些列名称为"AS bad"。 - numeral
1
@numeral 底层的JVM代码是否暴露出任何可以用来代替手动编写解析器逻辑的功能? - shadowtalker
1
@shadowtalker 在检查了 https://spark.apache.org/docs/2.2.0/api/java/index.html?org/apache/spark/sql/Column.html 后似乎不是这样的。 - numeral
别名也可以不使用任何正则表达式来提取:str(column).split(' AS ')[1].split('`')[1] - ciurlaro

10
根据具体情况而定:
  1. 未别名化的列:column._jc.toString()已经可以正常工作了(感谢@numeral)。

  2. 别名化的列:(即column.alias("whatever"))可以提取别名:

    • Python

      str(column).split(" AS ")[1].split("`")[1] 
      
    • Scala

      str(column).split(" AS ")(1).split("`")(1)
      

6
如果您想要DataFrame的列名,您可以使用pyspark.sql类。 我不确定SDK是否支持通过列名显式索引DF。我收到了此回溯:
df.columns ['High'] 将返回TypeError: list indices must be integers, not str 但是,在您的数据框上调用columns方法将返回列名列表:
df.columns将返回['Date','Open','High','Low','Close','Volume','Adj Close']
如果要获取列数据类型,则可以调用dtypes方法:
df.dtypes将返回[('日期','时间戳'),('开放','双精度'),('高','双精度'),('低','双精度') ,('关','双精度'),('数量','整数'),('Adj Close','双精度')]
如果您想要特定的列,您需要按索引访问它:
df.columns [2]将返回'High'

按照这个思路:[x[0] for x in df.dtypes] - David C.

4

我发现答案非常非常简单...

// It is in Java, but it should be same in PySpark
Column col = ds.col("colName"); //the column object
String theNameOftheCol = col.toString();

变量theNameOftheCol的值是"colName"

6
在Python中,它将是 col._jc.toString()。 - justin cress
当列被别名化时,这将返回col_name AS alias,而期望的结果可能只是alias - ZygD

2

我希望这些选项可以更像通用选项。涉及的情况包括:

  • 没有别名的列
  • 有别名的列
  • 具有连续多个别名的列
  • 用反引号括起来的列名

无正则表达式:

str(col).replace("`", "").split("'")[-2].split(" AS ")[-1])

使用正则表达式:

import re
re.search(r"'.*?`?(\w+)`?'", str(col)).group(1)

0

由于没有任何答案被标记为答案 - 我可能过于简化了OP的问题,但是:

my_list = spark_df.schema.fields
for field in my_list:
    print(field.name)

0

#如果你有多个表,表名可以作为一个例子

loc = '/mnt/tablename' or 'whatever_location/table_name' #incase of external table or any folder 

table_name = ['customer','department']

for i in table_name:
  print(i) # printing the existing table name

  df = spark.read.format('parquet').load(f"{loc}{i.lower()}/") # creating dataframe from the table name
  for col in df.dtypes:
    print(col[0]) # column_name as per availability

    print(col[1]) # datatype information of the respective column

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接