Datatableのソート動作について

現在、社内教育用にデータスクレイピングを使用した簡易的なシナリオを作成しております。
動作としては、
1.Yahoo!ファイナンスから株価ランキングを開き
2.上位75までをデータスクレイピング後
3.Datatableを出来高で並び替えて、Excelファイルに出力し保存
になります。
現状、3番で問題が発生しており、出来高を降順でソートしても正常にソートされず、順序がバラバラになってしまいます。

この場合どのようにすれば正常にソートされるようになりますでしょうか。
ご教示お願いいたします。

データスクレイピングした結果の列属性がObjectであるため、文字列として評価されてしまっています。一度、ForEachRowで、該当列に対して、「代入」アクティビティで数値として再格納してみてください。

左辺:Row.Item(“出来高 出来高”)
右辺:CInt(Row.Item(“出来高 出来高”))

こんにちは

Yahooファイナンスはスクレイピングが禁止されていたかと思いますが、とりあえず技術的なところだけ。

原因は @HANACCHI さんも書かれていますとおり文字列としてのソートになっているようです。 (値にカンマも含まれていますし...)

ヘッダ名等は微調整が必要かもしれませんが、概ね以下で並べ替えできるかと思います。

ExtractDataTable = ExtractDataTable.AsEnumerable.OrderBy(function(r) CInt(r("出来高 出来高").ToString.Trim.Replace(",",""))).CopyToDataTable

ご回答ありがとうございます。
よく見ると、9の値、8の値、7の値、、、となっていました。
気づきませんでした。ご指摘ありがとうございます。

@Yoichi さんの回答と合わせて、一度シナリオを組み直したいと思います。

今後ともよろしくお願いします。

1 Like

こんにちは
ご回答ありがとうございます。

Yahoo!ファイナンスのデータスクレイピング禁止のご指摘ありがとうございます。
今後、調べてから使用するようにいたします。

Java専門なため、.NETのコードは学習中なので一つ一つ調べながら組んでみます。

ありがとうございました。

1 Like

解決しそうですね。

解決のHINTになった書き込みの解決策にチェックをお願いしますね。

スクレイピングをYahoo!ファイナンスからデモサイトに変更しました。

@HANACCHI 様の方法で試しましたが、上手くソートできませんでした。

@Yoichi 様の方法で期待通りのソートができましたが、
初心者には見た目が難しくとっつきづらくなってしまう可能性があるため、
アクティビティを使用した方法で視覚的に分かるようにしたいです。

ForEachRowを使用した後のDataTable内のデータは以下のようになっており、
数値に上手く変換できていないように見えます。

DataRow
{
HasErrors=false,
ItemArray=object[6] ←6項目全てObj型のまま
{
“1”,
“雑費”,
“仮払”,
“8110”, ←変換できていない?
“”,
“2018/07/24 10:54:26”
},
RowError="",
RowState=Added,
Table=[DataTable]
},

CInt以外の変換(Convert.Int32など)も試しましたが、同様の結果でした。
回答いただいたこと以外で何か考えられる可能性がありましたら、
追加で教えていただきたく思います。

よろしくお願いいたします。

この右辺を、
CInt(row.item(“出来高 出来高”).ToString.Trim.Replace(",",""))
に変えてみます。。。

Object型を文字列化し、トリムしてから、カンマを除去した値をInt型に変換。。。

こんにちは

途中の処理が分かりませんので推定が入りますが、
DataTableのColumnには型が定義されておりますので、単なる上書きでは型は変更されないと思います。またデータがある状態での列の型の変更はできない仕様かと思います。
そのため
1.既存のDataTableに対して新規にInt32型等の数値型の列を追加して、そちらに数値型に変換した値を入力していき、この列でソートする。
2.あらたにDataTableを構築する。
等が対応として考えられると思います。

1は、Add Data Column(データ列を追加)アクティビティを
2は、Build DataTable (データテーブルを構築)アクティビティを
それぞれ使うことになるかと思います。

@HANACCHI 様ご回答ありがとうございます。
ちょうどその方法を検証しましたが、できませんでした。

@Yoichi 様ご回答ありがとうございます。
私も、変数をキャストするだけでデータテーブルの型を変更できるのか、
気になったためちょうど検証をしたところなので報告させていただきますね。

仮で以下のようなテーブルを作成し、列名:Objに対して
@HANACCHI さんの方法で変換をかけたところ上手く変換することができました。
データテーブル構築
変換前の変数の中身は以下になります。

DataRow
{
HasErrors=false,
ItemArray=object[3] ←変数型に関係なく、全てObj型で入っているようです。
{
“test1”,
1,
“1” ←Objで入っている
},
RowError="",
RowState=Added,
Table=[TableName]
},

変換後の変数の中身

DataRow
{
HasErrors=false,
ItemArray=object[3] ←変数型に関係なく、全てObj型で入っているようです。
{
“test1”,
1,
1 ←"“が取れていたのでIntに変換できている
},
RowError=”",
RowState=Added,
Table=[TableName]
},

カラムの型(変換前も後も変化はありませんでした)

DataColumnCollection(3)
{
[Str],
[Int],
[Obj]
}

Yahooファイナンスやデモサイトでできない理由についてはもう少し調査してみます。

こんにちは

EXCELなどからの読み込みの場合は列の型がObject型になると思いますが、スクレイピングの場合String型になっていると思います。
Object型の場合個々のデータに型情報をもっているので、列の型情報によらず文字列、数値ともに格納できますが、String型の場合はそれができないので、列自体の型を意識する必要があるかと思います。

1 Like

データテーブルのフィルタ機能を使うときは、同じ列に対してキャストしてできた実績があったんですけどねぇ。。。(^^♪

スクレイピングした場合の列の型情報の確認方法があれば教えていただけませんでしょうか。
データテーブルを構築から作成した場合、デバッグ時にDataColumnCollectionに型情報が記録されていますが、スクレイピングした場合はDataColumnCollectionが無いため、確認方法が分からない状態です。

個々のデータについては数値も文字列も全てStringで取得されていることが確認できました。

今回はこちらの方法で対応することとし、
教えるときにはObject型とその他の型の考え方についても伝えられるようにしたいと思います。

こんにちは

例えば以下をWriteLineなりMessgeBoxなりで出力すれば良いかと思います。列指定はindexだけでなく名前でも可能かと思います。

ExtractDataTable.Columns(0).DataType.ToString()

1 Like

すみません、こちらは型ではなく、列名でした。
なので変換前も後も変化はなくて当然の動作です。
訂正いたします。

@Yoichi さん
すみません、スクレイピング時もデータテーブルの手動構成時でも私の方では
確認方法は分かっておりませんでした。

@HANACCHI
@Yoichi
ご協力いただきありがとうございました。
まとめて終わりにしたいと思います。

■ソートが期待通りとならなかった理由

→列の型がStringのために文字列でのソートが行われていた。
→列の型をIntにする必要がある

■解決策

→今回は1の方法を使用した。
1.データスクレイピングで作成されたデータテーブルに対してAdd Data ColumnをInt32型で行う
2.ForEachRowでAssignをrow(“1の列名”) = CInt(row(“変換対象列名”))を行う
3.SortDataTableで1の列を指定し、降順ソート 以上

■DataTableの列属性の確認方法

■その他

3 Likes

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.