let's linqing! - c#におけるデータ処理 - by @masaru_b_cl #nds51

52
Let’s LINQing! - C#におけるデータ処理 - 2017/3/25 - #nds51 TAKANO Sho (高野 将)/ @ masaru_b_cl

Upload: -

Post on 22-Jan-2018

1.724 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Let’s LINQing!- C#におけるデータ処理 -

2017/3/25 - #nds51

TAKANO Sho(高野 将)/ @masaru_b_cl

Page 2: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

某SIerで働くDeveloper

そのかたわら執筆業も

自己紹介

#nds51 2

Page 3: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

自己紹介

NDS初期メンバーの一人

#nds51 3

Page 4: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

自己紹介

最近の参加状況

#nds51 4

Page 5: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

自己紹介

最近の参加状況

#nds51 5

なんと2年ぶり!

Page 6: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

自己紹介

最近の参加状況

#nds51 6

なんと2年ぶり!

不甲斐ない限り……

Page 7: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

自己紹介

#nds51 7

Niigata.NET https://ngtnet.connpass.com/ 発起人

Page 8: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Agenda

Introduction to LINQ

LINQ by Example

FAQ

#nds51 8

Page 9: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Introduction to LINQLINQとはなにか?

#nds51 9

Page 10: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

LINQとは?

Language-Integrated Query (LINQ) is an innovation introduced in

the .NET Framework version 3.5 that bridges the gap between the

world of objects and the world of data.

#nds51 10

統合言語クエリ (LINQ: Language-Integrated Query) は、Visual Studio

2008 および .NET Framework Version 3.5 の革新的な機能で、オブジェ

クトの世界とデータの世界の間の橋渡しをするものです。

Introduction to LINQ (C#)

https://msdn.microsoft.com/ja-jp/library/mt693042.aspx

Page 11: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

#nds51 11

おまえは何を言っているんだ?

Page 12: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

私の理解

あらゆるデータソースに

ほぼ同じようなコードで

クエリ(問い合わせ)発行

#nds51 12

Page 13: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Query for Anything

LINQ

CSV

XML

etc…

RDBMS

KVS

Excel

#nds51 13

Page 14: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

例えば

こんなCSVファイルがあったとしましょう

#nds51 14

Page 15: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

2017年分を日付の降順で

こんな感じでまっすぐなデータにしてやって

#nds51 15

var dataSource = File.ReadLines("traditional_syukujitsu.csv", Encoding.GetEncoding(932)).Select(line => line.Split(',')).Select(items => new [] {(Name: items[0], RawDate: items[1]),(Name: items[2], RawDate: items[3]),(Name: items[4], RawDate: items[5])

}).SelectMany(entries => entries).Where(entry => DateTime.TryParse(entry.RawDate, out var _)).Select(entry => (Date: DateTime.Parse(entry.RawDate), Name: entry.Name));

Page 16: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

2017年分を日付の降順で

あとは絞り込んで、並び替えて、書式指定

#nds51 16

dataSource.Where(h => h.Date >= new DateTime(2017, 1, 1)) // 絞り込み(filter).Where(h => h.Date <= new DateTime(2017, 12, 31)) // 絞り込み(filter).OrderByDescending(h => h.Date) // 並べ替え(sort).Select(h => $“{h.Date:yyyy/MM/dd} ( {h.Name} )”); // 書式指定(map)

Page 17: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

2017年分を日付の降順で

できた!

#nds51 17

Page 18: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

他にも

こんなCSVファイルがあったとしましょう

#nds51 18

国民の祝日について - 内閣府

http://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html

Page 19: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

var dataSource = File.ReadLines("syukujitsu.csv", Encoding.GetEncoding(932)).Select(line => line.Split(',')).Skip(1).Select(items => (Date: DateTime.Parse(items[0]), Name: items[1]));

dataSource.Where(h => h.Date >= new DateTime(2017, 1, 1)).Where(h => h.Date <= new DateTime(2017, 12, 31)).OrderByDescending(h => h.Date).Select(h => $"{h.Date:yyyy/MM/dd} ( {h.Name} )");

他にも

#nds51 19

Page 20: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

他にも

#nds51 20

var dataSource = File.ReadLines("syukujitsu.csv", Encoding.GetEncoding(932)).Select(line => line.Split(',')).Skip(1).Select(items => (Date: DateTime.Parse(items[0]), Name: items[1]));

dataSource.Where(h => h.Date >= new DateTime(2017, 1, 1)).Where(h => h.Date <= new DateTime(2017, 12, 31)).OrderByDescending(h => h.Date).Select(h => $"{h.Date:yyyy/MM/dd} ( {h.Name} )");

ひとつ前と完全に一致

Page 21: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

XMLも

#nds51 21

Page 22: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

var dataSource = XDocument.Load("Holidays.xml").Descendants("Holiday").Select(element =>(Date: DateTime.Parse(element.Element("Date").Value),Name: element.Element("Name").Value

));

dataSource.Where(h => h.Date >= new DateTime(2017, 1, 1)).Where(h => h.Date <= new DateTime(2017, 12, 31)).OrderByDescending(h => h.Date).Select(h => $"{h.Date:yyyy/MM/dd} ( {h.Name} )");

XMLも

#nds51 22

LINQ to XML

https://msdn.microsoft.com/ja-jp/library/bb387098.aspx

Page 23: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Excelも

#nds51 23

Page 24: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

var dataSource = new XLWorkbook("syukujitsu.xlsx").Worksheet(1).Rows().Skip(1).Select(row => (Date: (DateTime)row.Cell(1).Value, Name: row.Cell(2).Value as string));

dataSource.Where(h => h.Date >= new DateTime(2017, 1, 1)).Where(h => h.Date <= new DateTime(2017, 12, 31)).OrderByDescending(h => h.Date).Select(h => $"{h.Date:yyyy/MM/dd} ( {h.Name} )");

Excelも

#nds51 24

ClosedXML

https://github.com/closedxml/closedxml

Page 25: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

SQLiteも

#nds51 25

Page 26: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

var dataSource = new DataContext(new SQLiteConnection("Data Source=nds51.db")).GetTable<Holiday>();

dataSource.Where(h => h.Date >= new DateTime(2017, 1, 1)).Where(h => h.Date <= new DateTime(2017, 12, 31)).OrderByDescending(h => h.Date).Select(h => $"{h.Date:yyyy/MM/dd} ( {h.Name} )");

SQLiteも

#nds51 26

[Table(Name="Holiday")]class Holiday{

[Column]public DateTime Date { get; set; }[Column]public string Name { get; set; }

}

System.Data.SQLite

https://system.data.sqlite.org/index.html

Page 27: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Redisも

#nds51 27

Page 28: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

var dataSource = new (await new RedisList<Holiday>(new RedisSettings("127.0.0.1"),"holidays“

).Range()

).Select(holiday => (Date: holiday.Date.ToLocalTime(), // RedisはUnixTime(UTC)なので、JSTに変換

Name: holiday.Name));

dataSource.Where(h => h.Date >= new DateTime(2017, 1, 1)).Where(h => h.Date <= new DateTime(2017, 12, 31)).OrderByDescending(h => h.Date).Select(h => $"{h.Date:yyyy/MM/dd} ( {h.Name} )");

Redisも

#nds51 28

class Holiday{public DateTime Date { get; set; }public string Name { get; set; }

}

CloudStructures

https://github.com/neuecc/CloudStructures

Page 29: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

お分かりただけただろうか…?

LINQ

CSV

XML

etc…

RDBMS

KVS

Excel

#nds51 29

Page 30: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

LINQ by ExampleLINQの実例

#nds51 30

Page 31: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

お題

某企業の新入社員研修にて、

それぞれの課題ごとに

実績日数の傾向を確認したい

#nds51 31

Page 32: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

こんなデータがありまして

#nds51 32

Page 33: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

やること

カテゴリ、課題ごとに以下を集計

最小値

最大値

平均

標準偏差

#nds51 33

Page 34: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

第1段階

生データを集計しやすい形に整形する

#nds51 34

Page 35: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

第2段階

データを集計して各種の基本的な統計値を取得する

#nds51 35

Page 36: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

第3段階

ばらつきの大きい課題の傾向を把握するため、

標準偏差で並び替える

#nds51 36

Page 37: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

第4段階

カテゴリごとにばらつきの傾向を確認するため、

標準偏差の平均をとる

#nds51 37

Page 38: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

第5段階以降も同様に

知りたい指標に合わせて

好きなだけデータをいじれる!

#nds51 38

Page 39: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

FAQよくある質問

#nds51 39

Page 40: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. それってExcelでもできるのでは?

#nds51 40

Page 41: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. それってExcelでもできるのでは?

A. できます!

#nds51 41

Page 42: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. それってExcelでもできるのでは?

A. ただし…

あらゆるデータソースに対してできる?

リアルタイムにできる?

というような利点があります

(もちろんExcelでもがんばればできる)

#nds51 42

Page 43: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. それってPandasでもできるのでは?

#nds51 43

※PandasPython製のデータ解析ライブラリ。強い。

Page 44: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. それってPandasでもできるのでは?

#nds51 44

ジョジョの奇妙な冒険第三部(スターダストクルセイダース)第42話 ダービー・ザ・プレイヤーその3 より

A. Exactly!

(その通りでございます)

Page 45: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. それってPandasでもできるのでは?

#nds51 45

A. ただし…

使い慣れたツール(C#+LINQ)でやるのは、

間違いとは言い切れない

チームのスキルなどと相談すること

Page 46: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. どういう仕組みで動いてるの?

#nds51 46

Page 47: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. どういう仕組みで動いてるの?

A. イテレーターパターンと

デコレーターパターンの合わせ技

#nds51 47

Page 48: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. どういう仕組みで動いてるの?

イテレーター:値を列挙する

IEnumerable<T>

IEnumerator<T>を取得する

IEnumerator<T>

T型の値を列挙する

bool MoveNext()

T Current { get; }

#nds51 48

Page 49: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. どういう仕組みで動いてるの?

デコレーター

IEnumerable<T>に対する拡張メソッド

例)

IEnumerable<TResult> Select<TSource, TResult>(

this IEnumerable<TSource> source,

Func<T, TResult> selector)

#nds51 49

Page 50: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

Q. どういう仕組みで動いてるの?

何らかのコレクションをIEnumerable<T>にできれば、

あとは標準クエリ演算子等を組み合わせてやるだけ

#nds51 50

Select(射影)

Aggregate(畳み込み)

SelectMany(射影と平滑化)

Where(絞り込み)

OrderyBy(並び替え)

Page 51: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

まとめ

#nds51 51

Page 52: Let's LINQing! - C#におけるデータ処理 - by @masaru_b_cl #nds51

まとめ

C#でデータ処理するならまずはLINQ

LINQを使うとあらゆるデータソースのデータを

柔軟に変換したり集計できる

IEnumerable<T>で列挙できればOK

#nds51 52