Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何向Spark数据帧添加新列(使用PySpark)?_Python_Apache Spark_Dataframe_Pyspark_Apache Spark Sql - Fatal编程技术网

Python 如何向Spark数据帧添加新列(使用PySpark)?

Python 如何向Spark数据帧添加新列(使用PySpark)?,python,apache-spark,dataframe,pyspark,apache-spark-sql,Python,Apache Spark,Dataframe,Pyspark,Apache Spark Sql,我有一个Spark数据框架(使用PySpark 1.5.1),并希望添加一个新列 我尝试了以下方法,但没有成功: type(randomed_hours) # => list # Create in Python and transform to RDD new_col = pd.DataFrame(randomed_hours, columns=['new_col']) spark_new_col = sqlContext.createDataFrame(new_col) my_

我有一个Spark数据框架(使用PySpark 1.5.1),并希望添加一个新列

我尝试了以下方法,但没有成功:

type(randomed_hours) # => list

# Create in Python and transform to RDD

new_col = pd.DataFrame(randomed_hours, columns=['new_col'])

spark_new_col = sqlContext.createDataFrame(new_col)

my_df_spark.withColumn("hours", spark_new_col["new_col"])
使用此命令时也出现错误:

my_df_spark.withColumn("hours",  sc.parallelize(randomed_hours))

那么,如何使用PySpark将新列(基于Python向量)添加到现有的数据帧中呢?

您不能将任意列添加到Spark中的
数据帧中。只能使用文字创建新列(其他文字类型如中所述)

转换现有列:

from pyspark.sql.functions import exp

df_with_x5 = df_with_x4.withColumn("x5", exp("x3"))
df_with_x5.show()

## +---+---+-----+---+--------------------+
## | x1| x2|   x3| x4|                  x5|
## +---+---+-----+---+--------------------+
## |  1|  a| 23.0|  0| 9.744803446248903E9|
## |  3|  B|-23.0|  0|1.026187963170189...|
## +---+---+-----+---+--------------------+
包括使用
join

from pyspark.sql.functions import exp

lookup = sqlContext.createDataFrame([(1, "foo"), (2, "bar")], ("k", "v"))
df_with_x6 = (df_with_x5
    .join(lookup, col("x1") == col("k"), "leftouter")
    .drop("k")
    .withColumnRenamed("v", "x6"))

## +---+---+-----+---+--------------------+----+
## | x1| x2|   x3| x4|                  x5|  x6|
## +---+---+-----+---+--------------------+----+
## |  1|  a| 23.0|  0| 9.744803446248903E9| foo|
## |  3|  B|-23.0|  0|1.026187963170189...|null|
## +---+---+-----+---+--------------------+----+
或使用函数/udf生成:

from pyspark.sql.functions import rand

df_with_x7 = df_with_x6.withColumn("x7", rand())
df_with_x7.show()

## +---+---+-----+---+--------------------+----+-------------------+
## | x1| x2|   x3| x4|                  x5|  x6|                 x7|
## +---+---+-----+---+--------------------+----+-------------------+
## |  1|  a| 23.0|  0| 9.744803446248903E9| foo|0.41930610446846617|
## |  3|  B|-23.0|  0|1.026187963170189...|null|0.37801881545497873|
## +---+---+-----+---+--------------------+----+-------------------+
在性能方面,映射到Catalyst表达式的内置函数(
pyspark.sql.functions
)通常比Python用户定义函数更受欢迎

如果要将任意RDD的内容添加为列,可以

  • 在RDD上调用
    zipWithIndex
    ,并将其转换为数据帧
  • 使用索引作为联接键联接两者

要使用自定义项添加列,请执行以下操作:

df = sqlContext.createDataFrame(
    [(1, "a", 23.0), (3, "B", -23.0)], ("x1", "x2", "x3"))

from pyspark.sql.functions import udf
from pyspark.sql.types import *

def valueToCategory(value):
   if   value == 1: return 'cat1'
   elif value == 2: return 'cat2'
   ...
   else: return 'n/a'

# NOTE: it seems that calls to udf() must be after SparkContext() is called
udfValueToCategory = udf(valueToCategory, StringType())
df_with_cat = df.withColumn("category", udfValueToCategory("x1"))
df_with_cat.show()

## +---+---+-----+---------+
## | x1| x2|   x3| category|
## +---+---+-----+---------+
## |  1|  a| 23.0|     cat1|
## |  3|  B|-23.0|      n/a|
## +---+---+-----+---------+
为了


添加列名称时,可以定义新的
udf

u_f = F.udf(lambda :yourstring,StringType())
a.select(u_f().alias('column_name')

我想为一个非常类似的用例提供一个通用示例:

用例:我有一个csv,包括:

First|Third|Fifth
data|data|data
data|data|data
...billion more lines
我需要执行一些转换,最终的csv需要看起来像

First|Second|Third|Fourth|Fifth
data|null|data|null|data
data|null|data|null|data
...billion more lines
我之所以需要这样做,是因为这是由某个模型定义的模式,我需要最终的数据能够与SQL批量插入之类的东西进行互操作

因此:

1) 我使用spark.read读取原始csv,并将其命名为“df”

2) 我对数据做了一些修改

3) 我使用以下脚本添加空列:

outcols = []
for column in MY_COLUMN_LIST:
    if column in df.columns:
        outcols.append(column)
    else:
        outcols.append(lit(None).cast(StringType()).alias('{0}'.format(column)))

df = df.select(outcols)

通过这种方式,您可以在加载csv后构建架构(如果您必须对许多表执行此操作,也可以对列进行重新排序)。

添加列的最简单方法是使用“withColumn”。由于dataframe是使用sqlContext创建的,因此必须指定模式,否则默认情况下可以在数据集中使用。如果指定了模式,每次更改时工作负载都会变得单调乏味

以下是您可以考虑的示例:

from pyspark.sql import SQLContext
from pyspark.sql.types import *
sqlContext = SQLContext(sc) # SparkContext will be sc by default 

# Read the dataset of your choice (Already loaded with schema)
Data = sqlContext.read.csv("/path", header = True/False, schema = "infer", sep = "delimiter")

# For instance the data has 30 columns from col1, col2, ... col30. If you want to add a 31st column, you can do so by the following:
Data = Data.withColumn("col31", "Code goes here")

# Check the change 
Data.printSchema()

我们可以通过以下步骤直接向DataFrame添加其他列:

from pyspark.sql.functions import when
df = spark.createDataFrame([["amit", 30], ["rohit", 45], ["sameer", 50]], ["name", "age"])
df = df.withColumn("profile", when(df.age >= 40, "Senior").otherwise("Executive"))
df.show()

有多种方法可以在pySpark中添加新列

让我们首先创建一个简单的数据帧

date = [27, 28, 29, None, 30, 31]
df = spark.createDataFrame(date, IntegerType())
现在,让我们尝试将列值加倍,并将其存储在新列中。PFB有几种不同的方法可以实现相同的效果

# Approach - 1 : using withColumn function
df.withColumn("double", df.value * 2).show()

# Approach - 2 : using select with alias function.
df.select("*", (df.value * 2).alias("double")).show()

# Approach - 3 : using selectExpr function with as clause.
df.selectExpr("*", "value * 2 as double").show()

# Approach - 4 : Using as clause in SQL statement.
df.createTempView("temp")
spark.sql("select *, value * 2 as double from temp").show()
有关spark DataFrame函数的更多示例和说明,请访问我的


我希望这会有所帮助。

添加新列,其中包含一些自定义值或动态值计算,这些计算将基于现有列进行填充

e、 g

新的ColumnC为ColumnA+ColumnB

|ColumnA | ColumnB | ColumnC|
|--------|---------|--------|
| 10     | 15      | 25     |
| 10     | 20      | 30     |
| 10     | 30      | 40     |
使用


input\u dataframe
是将被修改的数据框,并且
customColumnVal
函数具有添加新列的代码。

需要为df.select('*',(df.age+10).alias('agePlusTen'))谢谢,如果您输入
df=df.select('*',(df.age+10).alias('agePlusTen'))
您实际上是在添加任意列,因为@zero323在上面警告我们这是不可能的,除非在Spark中这样做有什么问题,在Pandas中,这是标准的方式..pySpark有这样的版本吗?@Tagar上面的代码片段是python。@GeoffreyAnderson,
df.select('*',df.age+10,df.age+20)
您需要调用
StringType()
“只有使用文字才能创建新列”文字在本文中的确切含义是什么?Spark的文档非常棒,请参阅df。withColumn Spark文档非常棒,因为它为精明的读者留下了大量的使用空间。Spark(和Pyspark)涵盖了一个名副其实的数据结构动物园,很少或根本没有关于如何在其中转换的说明。举个例子:像这样的问题层出不穷。如果col31值是lke df['keyName']的值,你会怎么做?
date = [27, 28, 29, None, 30, 31]
df = spark.createDataFrame(date, IntegerType())
# Approach - 1 : using withColumn function
df.withColumn("double", df.value * 2).show()

# Approach - 2 : using select with alias function.
df.select("*", (df.value * 2).alias("double")).show()

# Approach - 3 : using selectExpr function with as clause.
df.selectExpr("*", "value * 2 as double").show()

# Approach - 4 : Using as clause in SQL statement.
df.createTempView("temp")
spark.sql("select *, value * 2 as double from temp").show()
|ColumnA | ColumnB |
|--------|---------|
| 10     | 15      |
| 10     | 20      |
| 10     | 30      |
|ColumnA | ColumnB | ColumnC|
|--------|---------|--------|
| 10     | 15      | 25     |
| 10     | 20      | 30     |
| 10     | 30      | 40     |
#to add new column
def customColumnVal(row):
rd=row.asDict()
rd["ColumnC"]=row["ColumnA"] + row["ColumnB"]

new_row=Row(**rd)
return new_row
----------------------------
#convert DF to RDD
df_rdd= input_dataframe.rdd

#apply new fucntion to rdd
output_dataframe=df_rdd.map(customColumnVal).toDF()