2015-12-03 30 views
44

Tôi đến từ nền gấu trúc và đang sử dụng để đọc dữ liệu từ các tập tin CSV vào một dataframe và sau đó chỉ cần thay đổi tên cột một cái gì đó hữu ích bằng cách sử dụng lệnh đơn giản:Làm thế nào để thay đổi tên cột dataframe trong pyspark?

df.columns = new_column_name_list 

Tuy nhiên, tương tự không làm việc trong pyspark dataframes được tạo bằng sqlContext. Giải pháp duy nhất tôi có thể tìm ra để làm điều này một cách dễ dàng như sau:

df = sqlContext.read.format("com.databricks.spark.csv").options(header='false', inferschema='true', delimiter='\t').load("data.txt") 
oldSchema = df.schema 
for i,k in enumerate(oldSchema.fields): 
    k.name = new_column_name_list[i] 
df = sqlContext.read.format("com.databricks.spark.csv").options(header='false', delimiter='\t').load("data.txt", schema=oldSchema) 

này về cơ bản là xác định các biến hai lần và suy luận giản đồ đầu tiên sau đó đổi tên các tên cột và sau đó tải dataframe lại với giản đồ được cập nhật .

Có cách nào tốt hơn và hiệu quả hơn để làm điều này giống như chúng tôi làm trong gấu trúc không?

phiên bản spark tôi là 1.5.0

Trả lời

114

Có rất nhiều cách để làm điều đó:

  • Lựa chọn 1. Sử dụng selectExpr.

    data = sqlContext.createDataFrame([("Alberto", 2), ("Dakota", 2)], 
                ["Name", "askdaosdka"]) 
    data.show() 
    data.printSchema() 
    
    # Output 
    #+-------+----------+ 
    #| Name|askdaosdka| 
    #+-------+----------+ 
    #|Alberto|   2| 
    #| Dakota|   2| 
    #+-------+----------+ 
    
    #root 
    # |-- Name: string (nullable = true) 
    # |-- askdaosdka: long (nullable = true) 
    
    df = data.selectExpr("Name as name", "askdaosdka as age") 
    df.show() 
    df.printSchema() 
    
    # Output 
    #+-------+---+ 
    #| name|age| 
    #+-------+---+ 
    #|Alberto| 2| 
    #| Dakota| 2| 
    #+-------+---+ 
    
    #root 
    # |-- name: string (nullable = true) 
    # |-- age: long (nullable = true) 
    
  • Tùy chọn 2. Sử dụng withColumnRenamed, lưu ý rằng phương pháp này cho phép bạn "ghi đè" cùng một cột.

    oldColumns = data.schema.names 
    newColumns = ["name", "age"] 
    
    df = reduce(lambda data, idx: data.withColumnRenamed(oldColumns[idx], newColumns[idx]), xrange(len(oldColumns)), data) 
    df.printSchema() 
    df.show() 
    
  • Tùy chọn 3. sử dụng alias, tại Scala bạn cũng có thể sử dụng as.

    from pyspark.sql.functions import * 
    
    data = data.select(col("Name").alias("name"), col("askdaosdka").alias("age")) 
    data.show() 
    
    # Output 
    #+-------+---+ 
    #| name|age| 
    #+-------+---+ 
    #|Alberto| 2| 
    #| Dakota| 2| 
    #+-------+---+ 
    
  • Tùy chọn 4. Sử dụng sqlContext.sql, cho phép bạn sử dụng các truy vấn SQL trên DataFrames đăng ký dưới dạng bảng.

    sqlContext.registerDataFrameAsTable(data, "myTable") 
    df2 = sqlContext.sql("SELECT Name AS name, askdaosdka as age from myTable") 
    
    df2.show() 
    
    # Output 
    #+-------+---+ 
    #| name|age| 
    #+-------+---+ 
    #|Alberto| 2| 
    #| Dakota| 2| 
    #+-------+---+ 
    
+0

tôi đã làm nó với một 'loop for' +' withColumnRenamed', nhưng tùy chọn 'reduce' của bạn là rất đẹp :) –

+0

@FelipeGerard rằng là một ý tưởng rất xấu –

+0

Cũng vì không có gì được thực hiện trong Spark cho đến khi một hành động được gọi là trên DF, nó chỉ là mã ít thanh lịch ... Cuối cùng kết quả DF là chính xác như nhau! –

35
df = df.withColumnRenamed("colName", "newColName").withColumnRenamed("colName2", "newColName2") 

Advantage của việc sử dụng theo cách này: Với danh sách dài các cột mà bạn muốn thay đổi chỉ vài tên cột. Điều này có thể rất thuận tiện trong các tình huống này. Rất hữu ích khi tham gia các bảng có tên cột trùng lặp.

+0

có một biến thể của giải pháp này để lại tất cả các cột khác không? với phương pháp này và các phương pháp khác, chỉ các cột được đặt tên rõ ràng vẫn còn (tất cả các cột khác được xóa) – Quetzalcoatl

5

Nếu bạn muốn đổi tên một cột duy nhất và giữ phần còn lại vì nó là:

from pyspark.sql.functions import col 
new_df = old_df.select(*[col(s).alias(new_name) if s == column_to_change else s for s in old_df.columns]) 
5

Nếu bạn muốn thay đổi tất cả các tên cột, hãy thử df.toDF(*cols)

0

Đối với một cột duy nhất đổi tên, bạn có thể vẫn sử dụng toDF(). Ví dụ,

df1.selectExpr("SALARY*2").toDF("REVISED_SALARY").show() 
0

tôi sử dụng cái này:

from pyspark.sql.functions import col 
df.select(['vin',col('timeStamp').alias('Date')]).show() 
+0

Điều này không cung cấp câu trả lời cho câu hỏi. Khi bạn có đủ [danh tiếng] (https://stackoverflow.com/help/whats-reputation), bạn sẽ có thể [nhận xét về bất kỳ bài đăng nào] (https://stackoverflow.com/help/privileges/comment); thay vào đó, [cung cấp câu trả lời không yêu cầu làm rõ từ người hỏi] (https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can- i-do-thay thế). - [Từ đánh giá] (/ đánh giá/bài đăng chất lượng thấp/18681369) –

+0

Trong khi đoạn mã này có thể giải quyết được câu hỏi, [bao gồm giải thích] (http://meta.stackexchange.com/questions/114762/explaining-entirely -code-based-answers) thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. – Isma

Các vấn đề liên quan