データサイエンス100本ノックをAlteryxで。80日目(解答)

100本ノック

このページは解答編です。

↓ネ

↓タ

↓バ

↓レ

↓防

↓止

答えと解説

設問はこちらでした。

P-080: 商品データ(product.csv)のいずれかの項目に欠損が発生しているレコードを全て削除した新たな商品データを作成せよ。なお、削除前後の件数を表示させ、079で確認した件数だけ減少していることも確認すること。

解答ワークフローは以下のようになります。

今回は、欠損値が1フィールドでも存在するレコードがあれば除外する、ということになります。

シンプルな方法

まず、シンプルにフィルターツールを地道に使っていく方法をやってみましょう。

各フィールドがNullでなければ良いということなので、「!IsNull([フィールド名])」という計算式がまず使えます。これを各フィールドに対して実行し、AND条件で繋げればOKです。つまり、以下のような計算式となります。

!IsNull([product_cd]) AND 
!IsNull([category_major_cd]) AND 
!IsNull([category_medium_cd]) AND
!IsNull([category_small_cd]) AND
!IsNull([unit_price]) AND
!IsNull([unit_cost])

フィールド数が多いとなかなかめんどくさいです。

これをフィルターツールのカスタムフィルターで表現しましょう。

あとは、レコードカウントツールでカウントを取り、セレクトツールでフィールド名を「削除後」と変更します。

また、削除前のカウントは、product.csvの直後にレコードカウントツールを接続し、さらにセレクトツールでフィールド名を「削除前」とします。

これらを結合ツールで結合します。オプションとして、「レコードポジションで結合」で結合します。

このオプションは、レコードの先頭からの位置が同じものを横に並べていきます。

これで完了となります。実際のワークフローは以下の通りとなります。

シンプルではありますが、フィルターツールの設定の際に、フィールド数が多いと非常に大変です。

別解1:動的にやってみる(Nullがないもののみにする)

次に、各レコードを一度縦持ちにした後、フィルターでNullを除外した後、各レコードのカウントを取ると、Nullではないフィールドの数が得られます。これが全体のフィールド数より少ないレコードを除外する、という方法になります。

まず、最初に各レコードが何行目に位置するのか、IDをつけます。これにはレコードIDツールを使います。

次に、RecordIDフィールド以外すべて縦持ちにします。これには、転置ツールを用います。

これで、各フィールドが縦持ちになる(キー列とした「RecordID」以外に、「Name」「Value」という2つのフィールドで構成されるようになります)ので、「Value」列からNullをフィルターツールを使って取り除きます。

これにより、今回であれば元々6フィールドあったので、各RecordIDに対して6レコードずつ生成されていると思います。ただ、Nullを除外しているので、6レコードにならないRecordIDが出てきます。今回は、6レコード揃っているRecordIDを特定し、元々のデータストリームのRecordIDと合致させれば欲しいデータが得られます。

つまり、まず各RecordIDでグループ化してカウントを取ります。

このカウントが6個ずつあるものだけ抽出します。実はこのやり方はここだけ動的ではありませんが、今回はこのままにしておきましょう。動的に行う方法を考えてみていただければと思います。

ここからレコードIDツール直後のデータと結合します。この場合のキーフィールドはRecordIDフィールドです。

ここでは、右側から来たデータは不要なのでチェックをはずします。

この段階では上のようなワークフローとなっています。

この結合ツールのJ出力に、レコードカウントツールとセレクトツールを接続することで、削除後のカウントが得られます。

後は、削除前のカウントを取れればいいので、レコードIDツール以前であればどこに接続しても良いのですが、レコードカウントツールでカウントを取り、さらにセレクトツールで名称を変更します。

最終的なワークフローは以下の通りとなります。

別解2:動的にやってみる(Nullが発生しているものを除外)

次に、別解1と似た手法で別のやり方でやってみましょう。

前回は、Nullがないレコードを残す、という方法でしたが、今度はNullがあるレコードを除外する、という方法になります。なお、途中までは別解1と同じです。

まず、最初に各レコードが何行目に位置するのか、IDをつけます。これにはレコードIDツールを使います。

次に、RecordIDフィールド以外すべて縦持ちにします。これには、転置ツールを用います。

これで、各フィールドが縦持ちになる(キー列とした「RecordID」以外に、「Name」「Value」という2つのフィールドで構成されるようになります)。

ここまでは別解1と同様ですが、ここから異なるアプローチを取っていきます。

今回は、「Value」列でNullがあるもののみフィルターツールを使って抽出します。後にNullがあるRecordIDのレコードのみ結合ツールで除外していくためです。

ここでユニークツールを使って重複するレコードを除外します。実はユニークツールを使わなくても結果は同じです。ここではRecordIDフィールドに対してユニークを取ります。

ここからがポイントですが、結合ツールを使っていきます。L入力側はレコードIDツールの出力アンカーから接続します。R入力側は上のユニークツールの出力アンカーとなります。つまり、以下のようになります。

設定は以下の通り(別解1の結合ツールと設定は同じです)。

さて、このJ出力に出てきているデータはなんでしょうか?Nullを持つレコードと結合しているので、Nullが存在しています。つまり、削除対象のレコードです。逆に、Nullを持たないレコードはどこに出てきているのか?正解はL出力です。

参考に、J出力の結果を見てみると、以下のようにNullが存在しています。

ここからL出力にレコードカウントツールを接続し、セレクトツールで名前を変更していきます。

後は、別解1と同じように削除前カウントを取り、結合して終了です。最終的なワークフローは以下の通りとなります。

素直に行うなら、すべてのフィールドがNullがないという前提で進める別解1が本道に見えますが、実はNullがあればNGという別解2の方がツールも少なく処理できる、というところが工夫のしがいがあるところです。

まとめ

今回は欠損値が1つでもあるフィールドを除外するという問題でした。1行すべてがNullなら削除、ということであればデータクレンジングツールが使えるのですが、一部のみということであれば地道に行うしかありません。

実際のデータ加工でも、別解2のパターン(除外リストを作成し、結合ツールで取り除く)は比較的よく使うので、活用してみてください。

解答ワークフローダウンロード

コメント

タイトルとURLをコピーしました