注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。
トランスフォームに関するよくある質問を以下に示します。
一般的な情報については、トランスフォームのドキュメントを参照してください。
transforms-python で Parquet の代わりに CSV ファイルを保存できますか?transforms-python で Parquet の代わりに CSV ファイルを保存できますか?各トランスフォーム言語でこれを行う例を以下に示します。
Java
Copied!1 2 3foundryOutput.getDataFrameWriter(dataFrame) .setFormatSettings(DatasetFormatSettings.builder().format("csv").build()) .write();
Python
Copied!1 2 3 4 5 6 7from transforms.api import transform, Input, Output @transform( output=Output("/path/to/python_csv"), my_input=Input("/path/to/input") ) def my_compute_function(output, my_input): output.write_dataframe(my_input.dataframe(), output_format="csv")
SQL
Copied!1CREATE TABLE `/path/to/sql_csv` USING CSV AS SELECT * FROM `/path/to/input`
複数のトランスフォームやデータセットが必要な場合は、for ループを使用して作成できます。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21from transforms.api import transforms_df, Input, Output def transform_generator(sources): #type: (List[str]) -> List([transforms.api.Transform]) transforms = [] # この例では複数の入力データセットを使用します。また、複数の出力を # 1個の入力データセットから生成することもできます。 for source in sources: @transforms_df( Output('/sources/{source}/output'.format(source=source)), my_input=Input('/sources/{source}/input'.format(source=source)) ) def compute_function(my_input, source=source): # 関数内で source 変数をキャプチャするには、デフォルト値付きのキーワード引数として渡します。 return my_input.filter(my_input.source == source) transforms.append(compute_function) return transforms TRANSFORMS = transforms_generator(['src1', 'src2', 'src3'])
これで、モジュールの TRANSFORMS 属性をインポートし、各トランスフォームを手動でパイプラインに追加できます。
Copied!1 2 3 4import my_module my_pipeline = Pipeline() my_pipeline.add_transforms(*my_module.TRANSFORMS)
1個の入力を受け取り、同じビルドで複数のデータセットを出力する単一のトランスフォームにするには、以下のようにプログラムで実現することもできます。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25# `/examples/students_hair_eye_color` データセットを使用します students_input = foundry.input('/examples/students_hair_eye_color') students_input.dataframe().sort('id').show(n=3) +---+-----+-----+----+ | id| hair| eye| sex| +---+-----+-----+----+ | 1|Black|Brown|Male| | 2|Brown|Brown|Male| | 3| Red|Brown|Male| +---+-----+-----+----+ Note that this example only shows the top three rows. from transforms.api import transform, Input, Output @transform( hair_eye_color=Input('/examples/students_hair_eye_color'), males=Output('/examples/hair_eye_color_males'), females=Output('examples/hair_eye_color_females'), ) def brown_hair_by_sex(hair_eye_color, males, females): # type: (TransformInput, TransformOutput, TransformOutput) -> None brown_hair_df = hair_eye_color.dataframe().filter(hair_eye_color.dataframe().hair == 'Brown') males.write_dataframe(brown_hair_df.filter(brown_hair_df.sex == 'Male')) females.write_dataframe(brown_hair_df.filter(brown_hair_df.sex == 'Female'))
トランスフォームに関する詳しいヘルプや情報については、以下のドキュメントを参照してください。
トランスフォームへの入力はストリームを基盤とするファイルのようなオブジェクトなので、ファイルとして処理できます。そのため、ファイル全体をメモリーに読み込んだり、ディスクにコピーしたりすることを気にする必要がなく、はるかに大きなファイルを使用できます。
Python 3 に含まれる gzip パッケージと io パッケージを使用します。
Copied!1 2 3 4 5 6 7import gzip, io def process_file(file_stauts): fs = input_dataset.filesystem() with fs.open(file_status.path, 'rb') as f: gz = gzip.GzipFile(fileobj=f) br = io.BufferedReader(gz)
また、読み取り時に文字列を返すようにする場合は、ラップできます。
Copied!1tw = io.TextIOWrapper(br)
ファイルにエンコーディングがある場合は、それを指定できます。
Copied!1tw = io.TextIOWrapper(br, encoding='CP500')
トランスフォームに関する詳しいヘルプや情報については、以下のドキュメントを参照してください。
以下の例では、Java と Spark を使用して、zip アーカイブ内の各ファイルを並列で解凍します。単一の圧縮ファイル内で解凍処理を並列化する場合は、.bz2 のような分割可能なファイル形式を使用します。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44package com.palantir.transforms.java.examples; import com.google.common.io.ByteStreams; import com.palantir.transforms.lang.java.api.Compute; import com.palantir.transforms.lang.java.api.FoundryInput; import com.palantir.transforms.lang.java.api.FoundryOutput; import com.palantir.transforms.lang.java.api.ReadOnlyLogicalFileSystem; import com.palantir.transforms.lang.java.api.WriteOnlyLogicalFileSystem; import com.palantir.util.syntacticpath.Paths; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * これは Spark を使用してファイルを並列で解凍する例です。 * <p> * 処理はエグゼキューターに分散されます。 */ public final class UnzipWithSpark { @Compute public void compute(FoundryInput zipFiles, FoundryOutput output) throws IOException { ReadOnlyLogicalFileSystem inputFileSystem = zipFiles.asFiles().getFileSystem(); WriteOnlyLogicalFileSystem outputFileSystem = output.getFileSystem(); inputFileSystem.filesAsDataset().foreach(portableFile -> { // 「processWith」は、指定された入力ファイルの InputStream を提供します。 portableFile.processWithThenClose(stream -> { try (ZipInputStream zis = new ZipInputStream(stream)) { ZipEntry entry; // zip ファイル内の各ファイルを出力ファイルシステムに書き込みます。 while ((entry = zis.getNextEntry()) != null) { outputFileSystem.writeTo( Paths.get(portableFile.getLogicalPath().toString(), entry.getName()), outputStream -> ByteStreams.copy(zis, outputStream)); } return null; } catch (IOException e) { throw new RuntimeException(e); } }); }); } }
トランスフォームに関する詳しいヘルプや情報については、以下のドキュメントを参照してください。