2015-12-03 13 views
44

pochodzę pandy tle i jestem przyzwyczajony do odczytu danych z plików CSV do dataframe a potem po prostu zmienić nazwy kolumn na coś użytecznego przy użyciu prostego polecenia:Jak zmienić nazwy kolumn danych w pyspark?

df.columns = new_column_name_list 

Jednak samo nie działa w ramki danych pyspark utworzone za pomocą sqlContext. Jedynym rozwiązaniem mogłem zorientować się, aby to zrobić łatwo jest następujący:

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) 

To jest w zasadzie definiowania zmiennej dwukrotnie i wywodząc schematu pierwszy wtedy zmiana nazwy nazwy kolumn, a następnie ładowanie dataframe dzięki zaktualizowanej schematu .

Czy istnieje lepszy i skuteczniejszy sposób na zrobienie tego, tak jak robimy to w pandach?

Moja wersja jest iskra 1.5.0

Odpowiedz

114

Istnieje wiele sposobów, aby to zrobić:

  • wariant 1. Korzystanie 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) 
    
  • Wariant 2. Korzystanie withColumnRenamed zauważyć, że metoda ta pozwala na „nadpisać” tej samej kolumny.

    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() 
    
  • Opcja 3. użyciu alias, w Scali można również użyć 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| 
    #+-------+---+ 
    
  • Opcja 4. Korzystanie sqlContext.sql, który pozwala na korzystanie z zapytań SQL na DataFrames zarejestrowanych jako tabele.

    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

Zrobiłem go z 'for' pętli +' withColumnRenamed', ale twój 'opcja reduce' jest bardzo ładne :) –

+0

@FelipeGerard że to bardzo zły pomysł. –

+0

Cóż, ponieważ nic nie zostanie zrobione w Sparku, dopóki akcja nie zostanie wywołana w DF, jest to po prostu mniej elegancki kod ... Ostatecznie wynikowy DF jest dokładnie taki sam! –

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

Zaletą korzystania z tej drogi: Z długiej listy kolumn chcesz zmienić tylko kilka nazw kolumn. To może być bardzo wygodne w tych scenariuszach. Bardzo przydatne przy dołączaniu tabel ze zduplikowanymi nazwami kolumn.

+0

czy istnieje wariant tego rozwiązania, który pozostawia wszystkie pozostałe kolumny bez zmian? w przypadku tej metody i innych pozostały tylko wyraźnie nazwane kolumny (wszystkie pozostałe zostały usunięte). – Quetzalcoatl

5

Jeśli chcesz zmienić nazwę pojedynczą kolumnę, a resztę jak to jest:

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

Jeśli chcesz zmienić wszystkie nazwy kolumn, spróbuj df.toDF(*cols)

0

Dla pojedynczej kolumny zmienić, można nadal używać toDF(). Na przykład,

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

Używam tego:

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

Nie zapewnia to odpowiedzi na pytanie. Gdy masz już wystarczającą [reputację] (https://stackoverflow.com/help/whats-reputation), będziesz mógł [komentować dowolny wpis] (https://stackoverflow.com/help/privileges/comment); zamiast tego [dostarczaj odpowiedzi, które nie wymagają wyjaśnień od pytającego] (https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can- i-do-zamiast). - [Z recenzji] (/ opinia/niskiej jakości-posts/18681369) –

+0

Ten fragment kodu może rozwiązać pytanie, [w tym wyjaśnienie] (http://meta.stackexchange.com/questions/114762/explaining-entirely -code-based-answers) naprawdę pomaga poprawić jakość twojego posta. Pamiętaj, że odpowiadasz na pytanie przeznaczone dla czytelników w przyszłości, a te osoby mogą nie znać powodów sugestii dotyczących kodu. – Isma