2017-10-11 1 views
0

Ich möchte eine einzelne Spalte in BigQuery ändern und die aktualisierten Daten in eine neue Tabelle schreiben, ohne alle anderen Spalten von Hand manuell beibehalten zu müssen. Ich kann erreichen, was ich möchte mit dem folgenden Code tun:Ändern einer einzelnen BigQuery-Spalte und Schreiben in eine neue Tabelle

row = p | 'ReadFromBigQuery' >> beam.io.Read(beam.io.BigQuerySource(query=query))  
new_row = row | beam.Map(lambda x: (x["col1"], x["col2"], preprocess(x["text_col"])) 
output = new_row | beam.Map(lambda (col1, col2, processed_text): {"col1": col1, "col2": col2, "text": processed_text} 

output | beam.io.WriteToBigQuery(path_to_new_table) 

Dies erfordert jedoch mich im Wesentlichen schreiben und jede Spalte mit der Hand halten - wenn ich mehr als 100 Spalten hatte (oder wirklich sogar 10+ Spalten) Dies würde sehr schnell unordentlich und umständlich werden. Gibt es eine einfachere Möglichkeit, eine Funktion (preprocess() in diesem Beispiel) über eine Zeile auszuführen und nur diese Spalte zu aktualisieren und trotzdem die anderen Spalten zu behalten?

+0

Hinweis: versuchen Sie, Ihre Datenelemente nicht als Tupel darstellen, sondern als Wörterbücher. Dann können Sie .copy() verwenden, um das Wörterbuch zu kopieren, die Kopie wie gewünscht zu ändern und das geänderte Wörterbuch zurückzugeben. – jkff

+0

Ahh, also müsste das eine separate Funktion sein, die ein Wörterbuch akzeptiert und dann können die Änderungen dort vorkommen – reese0106

+0

@jkff überprüfe meine Antwort und lass mich wissen, ob das was du beabsichtigst :) – reese0106

Antwort

1

Dank @jkff habe ich herausgefunden, wie das geht. Die Funktion sollte ein Diktat aufnehmen und empfangen, und dann können Sie einfach das einzelne Element des Diktats ändern. Etwas wie:

new_row = row | beam.Map(lambda x: preprocess_text(x, col_to_transform='text_column')` 

Wo preprocess_text() wäre so etwas wie:

def preprocess_text(row, col_to_transform): 
    row_copy = row.copy() 
    line = row_copy[col_to_transform] 
    line = ... # preprocessing transform goes here 
    row_copy[col_to_transform] = line 

    return row_copy 
+0

Du musst eine Kopie von der erstellen Zeile statt das ursprüngliche Objekt zu ändern. Es ist nicht sicher, das aktuelle Element zu ändern, das an eine Transformation übergeben wird. – jkff

+0

@jkff danke für den Vorschlag. Ist es sicher, dass die Kopie innerhalb der Vorverarbeitungsfunktion erstellt wird? Oder würden Sie empfehlen, es woanders zu haben? – reese0106

+0

Ich kann nicht an einen anderen Ort denken, um es zu tun. Die Funktionen, die an beam.Map, beam.FlatMap, beam.ParDo, beam.Filter usw. übergeben werden, dürfen ihre Eingabeelemente nicht verändern (oder die bereits ausgegebenen Elemente modifizieren) - also elements behandeln von PCollections als unveränderlich. Also - Sie müssen die Kopie in der Vorverarbeitungsfunktion erstellen, wenn Sie diese ändern möchten. – jkff

Verwandte Themen