Làm cách nào để thêm một cột mới vào Spark DataFrame (sử dụng PySpark)?


127

Tôi có Spark DataFrame (sử dụng PySpark 1.5.1) và muốn thêm một cột mới.

Tôi đã thử những cách sau mà không thành công:

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"])

Cũng có một lỗi sử dụng này:

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

Vậy làm cách nào để thêm một cột mới (dựa trên vectơ Python) vào DataFrame hiện có với PySpark?

Câu trả lời:


206

Bạn không thể thêm một cột tùy ý vào một DataFrametrong Spark. Các cột mới chỉ có thể được tạo bằng cách sử dụng các chữ (các loại chữ khác được mô tả trong Cách thêm một cột không đổi trong Spark DataFrame? )

from pyspark.sql.functions import lit

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

df_with_x4 = df.withColumn("x4", lit(0))
df_with_x4.show()

## +---+---+-----+---+
## | x1| x2|   x3| x4|
## +---+---+-----+---+
## |  1|  a| 23.0|  0|
## |  3|  B|-23.0|  0|
## +---+---+-----+---+

chuyển đổi một cột hiện có:

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...|
## +---+---+-----+---+--------------------+

bao gồm sử dụng 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|
## +---+---+-----+---+--------------------+----+

hoặc được tạo bằng hàm / 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|
## +---+---+-----+---+--------------------+----+-------------------+

Các hàm dựng sẵn ( pyspark.sql.functions) có hiệu năng ( ), ánh xạ tới biểu thức Catalyst, thường được ưa thích hơn các hàm do người dùng Python xác định.

Nếu bạn muốn thêm nội dung của RDD tùy ý dưới dạng cột, bạn có thể


1
"Các cột mới chỉ có thể được tạo bằng cách sử dụng chữ" Chính xác nghĩa đen là gì trong ngữ cảnh này?
timbram

Tài liệu của Spark rất tuyệt, xem df.withColumn spark.apache.org/docs/2.1.0/api/python/ Kẻ
Steven Black

10
Tài liệu Spark là "tuyệt vời" chỉ ở chỗ nó để lại những luồng sử dụng tuyệt vời cho đến một bài tập cho người đọc thông minh. Spark (và Pyspark) bao gồm một sở thú cấu trúc dữ liệu thực sự, với rất ít hoặc không có hướng dẫn về cách chuyển đổi giữa chúng. Trường hợp tại điểm: phổ biến các câu hỏi như thế này.
Shadowtalker

62

Để thêm một cột bằng UDF:

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|
## +---+---+-----+---------+

30

Dành cho Spark 2.0

# assumes schema has 'age' column 
df.select('*', (df.age + 10).alias('agePlusTen'))

1
Cần phải là df.select ('*', (df.age + 10) .alias ('agePlusTen'))
Frank B.

1
Cảm ơn, và nếu bạn nhập, df = df.select('*', (df.age + 10).alias('agePlusTen'))bạn đang thêm một cột tùy ý một cách hiệu quả vì @ zero323 cảnh báo chúng tôi ở trên là không thể, trừ khi có điều gì đó không ổn khi thực hiện điều này trong Spark, ở Pandas, đó là cách tiêu chuẩn ..
thảo quả

Có một phiên bản này cho pySpark?
Tagar

@Tagar Đoạn trên là trăn.
Luke W

1
@GeoffreyAnderson,df.select('*', df.age + 10, df.age + 20)
Mark Rajcok 28/07/18

2

Có nhiều cách chúng ta có thể thêm một cột mới trong pySpark.

Trước tiên hãy tạo một DataFrame đơn giản.

date = [27, 28, 29, None, 30, 31]
df = spark.createDataFrame(date, IntegerType())

Bây giờ hãy thử nhân đôi giá trị cột và lưu trữ nó trong một cột mới. PFB một vài cách tiếp cận khác nhau để đạt được như nhau.

# 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()

Để biết thêm ví dụ và giải thích về các hàm Spark DataFrame, bạn có thể truy cập blog của tôi .

Tôi hi vọng cái này giúp được.


0

Bạn có thể xác định một cái mới udfkhi thêm một column_name:

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

0
from pyspark.sql.functions import udf
from pyspark.sql.types import *
func_name = udf(
    lambda val: val, # do sth to val
    StringType()
)
df.withColumn('new_col', func_name(df.old_col))

Bạn cần gọi StringType().
gberger

0

Tôi muốn đưa ra một ví dụ tổng quát cho trường hợp sử dụng rất giống nhau:

Ca sử dụng: Tôi có một csv bao gồm:

First|Third|Fifth
data|data|data
data|data|data
...billion more lines

Tôi cần thực hiện một số biến đổi và csv cuối cùng cần trông giống như

First|Second|Third|Fourth|Fifth
data|null|data|null|data
data|null|data|null|data
...billion more lines

Tôi cần phải làm điều này bởi vì đây là lược đồ được xác định bởi một số mô hình và tôi cần dữ liệu cuối cùng của mình có thể tương thích với các Chèn hàng loạt SQL và những thứ như vậy.

vì thế:

1) Tôi đọc csv gốc bằng spark.read và gọi nó là "df".

2) Tôi làm một cái gì đó cho dữ liệu.

3) Tôi thêm các cột null bằng cách sử dụng tập lệnh này:

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)

Theo cách này, bạn có thể cấu trúc lược đồ của mình sau khi tải csv (cũng sẽ hoạt động để sắp xếp lại các cột nếu bạn phải làm điều này cho nhiều bảng).


0

Cách đơn giản nhất để thêm một cột là sử dụng "withColumn". Vì dataframe được tạo bằng sqlContext, bạn phải chỉ định lược đồ hoặc theo mặc định có thể có sẵn trong tập dữ liệu. Nếu lược đồ được chỉ định, khối lượng công việc sẽ trở nên tẻ nhạt khi thay đổi mỗi lần.

Dưới đây là một ví dụ mà bạn có thể xem xét:

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()

0

Chúng tôi có thể thêm các cột bổ sung vào DataFrame trực tiếp với các bước dưới đây:

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()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.