Pyspark'ta veri çerçevesi sütun adları nasıl değiştirilir?


201

Pandalar arka plan geliyor ve CSV dosyalarından bir veri çerçevesine veri okuma ve daha sonra basit bir komut kullanarak yararlı bir şey sütun adlarını değiştirmeye alışkınım:

df.columns = new_column_name_list

Ancak, aynı sqlContext kullanılarak oluşturulan pyspark veri çerçevelerinde çalışmaz. Bunu kolayca yapmak için çözebileceğim tek çözüm şudur:

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)

Bu temelde değişkeni iki kez tanımlar ve önce şemayı çıkarır, ardından sütun adlarını yeniden adlandırır ve ardından veri şemasını güncellenmiş şema ile yeniden yükler.

Pandalarda yaptığımız gibi bunu yapmanın daha iyi ve daha etkili bir yolu var mı?

Kıvılcım versiyonum 1.5.0

Yanıtlar:


334

Bunu yapmanın birçok yolu vardır:

  • Seçenek 1. 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)
    
  • Seçenek 2. withColumnRenamed ile bu yöntemin aynı sütunun üzerine "yazmanıza" izin verdiğini unutmayın. Python3 için, yerini xrangeile range.

    from functools import reduce
    
    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()
    
  • Kullanarak Seçenek 3. takma Scala, ayrıca kullanabilirsiniz olarak .

    from pyspark.sql.functions import col
    
    data = data.select(col("Name").alias("name"), col("askdaosdka").alias("age"))
    data.show()
    
    # Output
    #+-------+---+
    #|   name|age|
    #+-------+---+
    #|Alberto|  2|
    #| Dakota|  2|
    #+-------+---+
    
  • Seçenek 4. sqlContext.sql kullanarak DataFramestablo olarak kaydedilmiş SQL sorgularını kullanabilirsiniz .

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

1
Bir fordöngü + ile yaptım withColumnRenamed, ancak reduceseçeneğiniz çok güzel :)
Felipe Gerard

1
DF'de bir eylem çağrılıncaya kadar Spark'da hiçbir şey yapılmadığı için, sadece daha az zarif bir kod ... Sonuçta ortaya çıkan DF tamamen aynı!
Felipe Gerard

2
@FelipeGerard Lütfen bu gönderiyi kontrol edin , çok sayıda sütununuz varsa kötü şeyler olabilir.
Alberto Bonsanto

1
@AlbertoBonsanto En iyi seçenek olan 100'den fazla sütun varsa sütun takma ad olarak nasıl seçilir

3
@NuValue, ilk önce from functools import reduce
koşmalısın

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

Bu şekilde kullanmanın avantajı: Uzun sütun listesiyle yalnızca birkaç sütun adını değiştirmek istersiniz. Bu, bu senaryolarda çok uygun olabilir. Yinelenen sütun adlarına sahip tablolara katılırken çok kullanışlıdır.


bu çözümün diğer tüm sütunları değiştirmeyen bir varyantı var mı? ve diğer yöntemlerle yalnızca açıkça adlandırılmış sütunlar kaldı (diğerleri kaldırıldı)
Quetzalcoatl

1
+1 benim için iyi çalıştı, sadece diğer sütunları değiştirmeden belirtilen sütunu düzenledi ve hiçbir sütun kaldırılmadı.
mnis.p

2
@Quetzalcoatl Bu komut, diğer tüm sütunları korurken yalnızca belirtilen sütunu değiştiriyor gibi görünüyor. Bu nedenle, potansiyel olarak birçok sütun adından yalnızca birini yeniden adlandırmak için harika bir komut
user989762

@ user989762: kabul edildi; ilk anlayışım bu konuda yanlıştı ...!
Quetzalcoatl

62

Tüm sütun adlarını değiştirmek istiyorsanız, şunu deneyin: df.toDF(*cols)


5
bu çözüm OP başına df.columns = new_column_name_list'e en yakın, hem ne kadar özlü hem de yürütülmesidir.
Quetzalcoatl

Bence bu en iyi cevap seçilmelidir
HanaKaze

Benim için panda veri çerçevesinden başlık isimleri alıyordum, bu yüzden sadece kullandımdf = df.toDF(*my_pandas_df.columns)
Nic Scozzaro

Bu cevap beni karıştırıyor. Eski sütun adlarından yeni adlara bir eşleme olmamalı mı? Bu cols, yeni sütun adları olacak ve yalnızca adların colssırasının veri çerçevesinin sütun sırasına karşılık geldiği varsayılarak çalışır mı?
rbatt

47

Tüm sütun adlarına basit bir dönüşüm uygulamak isterseniz, bu kod hile yapar: (Tüm boşlukları alt çizgi ile değiştiriyorum)

new_column_name_list= list(map(lambda x: x.replace(" ", "_"), df.columns))

df = df.toDF(*new_column_name_list)

@ User8117731 toDfhüner için teşekkürler .


14

Tek bir sütunu yeniden adlandırmak ve geri kalanını olduğu gibi tutmak istiyorsanız:

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

14

df.withColumnRenamed('age', 'age2')


1
Pankaj Kumar'ın cevabı ve Alberto Bonsanto'nun cevabı (sırasıyla 2016 ve 2015'ten itibaren) zaten kullanılmasını öneriyor withColumnRenamed.
Andrew Myers

Teşekkürler, evet ama birkaç farklı sözdizimi var, belki onları daha resmi bir cevapta toplamalıyız? data.withColumnRenamed (oldColumns [idx], newColumns [idx]) vs data.withColumnRenamed (sütun adı, yeni sütun adı), pyspark'ın hangi sürümünü kullandığınıza bağlı olduğunu düşünüyorum
Sahan Jayasumana

1
Bu farklı bir sözdizimi değil. Tek fark, sütun adlarınızı bir dizide saklamamanızdır.
Ed Bordin

13

kullandığım yaklaşım bu:

pyspark oturumu oluştur:

import pyspark
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('changeColNames').getOrCreate()

veri çerçevesi oluştur:

df = spark.createDataFrame(data = [('Bob', 5.62,'juice'),  ('Sue',0.85,'milk')], schema = ["Name", "Amount","Item"])

sütun adlarıyla df'yi görüntüle:

df.show()
+----+------+-----+
|Name|Amount| Item|
+----+------+-----+
| Bob|  5.62|juice|
| Sue|  0.85| milk|
+----+------+-----+

yeni sütun adlarıyla bir liste oluşturun:

newcolnames = ['NameNew','AmountNew','ItemNew']

df'nin sütun adlarını değiştirin:

for c,n in zip(df.columns,newcolnames):
    df=df.withColumnRenamed(c,n)

df'yi yeni sütun adlarıyla görüntüle:

df.show()
+-------+---------+-------+
|NameNew|AmountNew|ItemNew|
+-------+---------+-------+
|    Bob|     5.62|  juice|
|    Sue|     0.85|   milk|
+-------+---------+-------+

9

Herkes kullanmak isterse, bir pyspark veri çerçevesi için birden çok sütun yeniden adlandırmak için kullanımı kolay bir işlev yaptı:

def renameCols(df, old_columns, new_columns):
    for old_col,new_col in zip(old_columns,new_columns):
        df = df.withColumnRenamed(old_col,new_col)
    return df

old_columns = ['old_name1','old_name2']
new_columns = ['new_name1', 'new_name2']
df_renamed = renameCols(df, old_columns, new_columns)

Dikkatli olun, her iki liste de aynı uzunlukta olmalıdır.


1
Bu konuda iyi iş çıkardın. Gerçi ne gerekli için biraz overkill. Ve sadece df'yi geçebilirsiniz çünkü old_columnsaynı olacaktır df.columns.
Darth Egregious

7

Yalnızca bir sütunu yeniden adlandırmanın başka bir yolu (kullanarak import pyspark.sql.functions as F):

df = df.select( '*', F.col('count').alias('new_count') ).drop('count')

3

Bunu kullanıyorum:

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

2
Bu kod snippet'i soruyu çözebilir, ancak bir açıklama da dahil olmak üzere , yayınınızın kalitesini artırmaya yardımcı olur. Gelecekte okuyucular için soruyu cevapladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceğini unutmayın.
İsma

1

Veri çerçevenizin tüm sütunlarını yeniden adlandırmak için aşağıdaki işlevi kullanabilirsiniz.

def df_col_rename(X, to_rename, replace_with):
    """
    :param X: spark dataframe
    :param to_rename: list of original names
    :param replace_with: list of new names
    :return: dataframe with updated names
    """
    import pyspark.sql.functions as F
    mapping = dict(zip(to_rename, replace_with))
    X = X.select([F.col(c).alias(mapping.get(c, c)) for c in to_rename])
    return X

Yalnızca birkaç sütunun adını güncellemeniz gerekiyorsa, replace_with listesinde aynı sütun adını kullanabilirsiniz.

Tüm sütunları yeniden adlandırmak için

df_col_rename(X,['a', 'b', 'c'], ['x', 'y', 'z'])

Bazı sütunları yeniden adlandırmak için

df_col_rename(X,['a', 'b', 'c'], ['a', 'y', 'z'])

0

Tek bir sütun yeniden adlandırma için yine de toDF () kullanabilirsiniz. Örneğin,

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

0

Sütun adını yeniden adlandırmak için çeşitli yaklaşımlar kullanabiliriz.

Önce basit bir DataFrame oluşturalım.

df = spark.createDataFrame([("x", 1), ("y", 2)], 
                                  ["col_1", "col_2"])

Şimdi col_1 öğesini col_3 olarak yeniden adlandırmaya çalışalım. PFB de aynısını yapmak için birkaç yaklaşım.

# Approach - 1 : using withColumnRenamed function.
df.withColumnRenamed("col_1", "col_3").show()

# Approach - 2 : using alias function.
df.select(df["col_1"].alias("col3"), "col_2").show()

# Approach - 3 : using selectExpr function.
df.selectExpr("col_1 as col_3", "col_2").show()

# Rename all columns
# Approach - 4 : using toDF function. Here you need to pass the list of all columns present in DataFrame.
df.toDF("col_3", "col_2").show()

İşte çıktı.

+-----+-----+
|col_3|col_2|
+-----+-----+
|    x|    1|
|    y|    2|
+-----+-----+

Umarım bu yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.