ブログ移転のお知らせ
Sphinx を使ってブログを書きたい! ということで、移転することにした。
Python で解析 24
“Advent Calendar 2013 - Python で解析!” の二十四日目。実データの操作。
今回は、実際のデータを探ってみたい。ここまでのデータ操作を使って、簡単にできるところまで。
一応、これが Advent Calendar 2013 の最後。技術系の Advent Calendar では 25 までやるのが慣例のようだが、 Wikipedia で調べたら、 24 までと書いてあったからね!
1. 実データの取得
実データの取得がなかなか難しい…。ブログのネタ用に、データを探してみたのだが、なかなか都合のいいのが見つからない。ネタ的に、野球やサッカーなんかがよかったのだが、 PDF だったり、グラフ化された Web の記事だったり…で、 Pandas を試してみるのに、ちょうどいいのがなかなか見つからない。
政府系の Open Data の取り組みも、 Excel にレポート形式でまとめられてて、ちょっと加工してやらないと…といった感じで、軽いブログ記事でサクッと使うには、なかなか難しい。"DATA GO JP" ってのがあるのだが、フォーマットでは PDF が 4891 件でダントツの一位。う〜む、使えん…。CSV も 389 件あるが、放射濃度のデータがたくさんあって、クリスマスイブに取り上げるのもなぁ…。そんな中でも、レッドリストが使いやすくて、 Pands の練習にはちょうどいい感じ。テーマ的には、クリスマスイブなのに…とは思うが、探しまわるのに疲れたので、これで行くことにする。
import pandas as pd In [1]: import pandas as pd In [2]: df = pd.read_csv('http://www.sizenken.biodic.go.jp/va2007/va_2007.csv', encoding='Shift-JIS')
こんな感じで、 URL から直接 DataFrame が作れるのが便利。これで、クリスマスイブっぽいのが、見つかれば良かったのだが…。
2. 概要の把握
まずは、全体像を。
In [3]: df Out[3]: <class 'pandas.core.frame.DataFrame'> Int64Index: 13498 entries, 0 to 13497 Data columns (total 11 columns): 種コード 13498 non-null values 科名 13498 non-null values 和名 13498 non-null values 学名 13498 non-null values 都道府県コード 13498 non-null values 都道府県 13498 non-null values 平成12年レッドデータブック刊行時のランク 13498 non-null values 平成19年レッドリスト選定時のランク 13498 non-null values 2万5千地形図名 13315 non-null values メッシュコード 13498 non-null values 生育状況 13498 non-null values dtypes: float64(1), int64(2), object(8)
11 項目あって、int64 が 2 件しかないので、数値データではなく文字データのようだ。13,497 件のレコードがあり、ほとんどの項目に値が入っているが、"2万5千地形図名" には欠損があるようだ。"2万5千地形図名" を詳しくは知らないが、市町村名ぐらいで位置情報を特定できるものだと思われる。
軽く各項目の値も見ておく。
In [4]: df.head() Out[4]: 種コード 科名 和名 学名 都道府県コード 都道府県 \ 0 9240 ヒノキ リシリビャクシン Juniperus communis var. montana 1 北海道 1 60990 ヒルムシロ リュウノヒゲモ Potamogeton pectinatus 1 北海道 2 9240 ヒノキ リシリビャクシン Juniperus communis var. montana 1 北海道 3 9240 ヒノキ リシリビャクシン Juniperus communis var. montana 1 北海道 4 9240 ヒノキ リシリビャクシン Juniperus communis var. montana 1 北海道 平成12年レッドデータブック刊行時のランク 平成19年レッドリスト選定時のランク 2万5千地形図名 メッシュコード 生育状況 0 EN VU 鷹泊貯水池 654270 現存(生育) 1 VU NT 鵡川 634167 現存(生育) 2 EN VU 布部岳 644272 現存(生育) 3 EN VU 胆振福山 644222 現存(生育) 4 EN VU 神居古潭 654241 現存(生育)
11 項目もあるので、横には並べられなくて、分割して表示されている。横に並べて綺麗に見るには、 Excel とか…を使う方がいいだろう。
3. 欠損データの傾向調査
試しに、"2万5千地形図名" が入っていない都道府県を調べてみる。
In [5]: df[pd.isnull(df[u"2万5千地形図名"])][u'都道府県'].value_counts() Out[5]: 鹿児島県 58 東京都 19 静岡県 18 熊本県 13 大分県 8
ブログの都合上、トップ 5 だけ抜粋した。
で、きっと、生息地域の偏りと同じに違いない…と思って、全体の都道府県を調べてみる。
In [6]: df[u'都道府県'].value_counts() Out[6]: 北海道 798 岡山県 674 大分県 596 愛知県 537 山形県 533 宮城県 527 千葉県 519 長野県 453 三重県 437 鹿児島県 380
こっちはトップ 10 まで掲載してみたが、関連があるようには見えない。 念のため、統計的に調べてみる。
In [7]: s1 = df[u'都道府県'].value_counts() In [8]: s2 = df[pd.isnull(df[u"2万5千地形図名"])][u'都道府県'].value_counts() In [9]: In [9]: df1 = pd.DataFrame({u'都道府県1': s1}) In [10]: df2 = pd.DataFrame({u'都道府県2': s2}) In [11]: tmp = df1.join(df2) In [12]: tmp[u'都道府県2'] = tmp[u'都道府県2'].fillna(0) # 欠損データがなかったところに 0 を補完する。 In [13]: tmp.corr() # 相関係数 Out[13]: 都道府県1 都道府県2 都道府県1 1.000000 0.163086 都道府県2 0.163086 1.000000
相関係数 0.16 ってことで、生息地域の偏りとは関係なさそうだ。
品種によって生息地が特定しにくい…とかあるのだろうか?
In [14]: s1 = df[u'科名'].value_counts() In [15]: s2 = df[pd.isnull(df[u"2万5千地形図名"])][u'科名'].value_counts() In [16]: In [16]: df1 = pd.DataFrame({u'科名1': s1}) In [17]: df2 = pd.DataFrame({u'科名2': s2}) In [18]: tmp = df1.join(df2) In [19]: tmp[u'科名2'] = tmp[u'科名2'].fillna(0) # 欠損データがなかったところに 0 を補完する。 In [20]: tmp.corr() # 相関係数 Out[20]: 科名1 科名2 科名1 1.000000 0.778866 科名2 0.778866 1.000000
相関係数 0.78 ってことで、正の相関があるようなのだが、納得するには、もう一歩。
In [21]: df1.head(10) Out[21]: 科名1 キク 1605 カヤツリグサ 909 ゴマノハグサ 850 シソ 838 タヌキモ 801 タデ 628 ガガイモ 582 トチカガミ 533 ヒルムシロ 460 ミクリ 386
In [22]: df2.head(10) Out[22]: 科名2 カヤツリグサ 23 キク 20 シソ 12 アカネ 10 ゴマノハグサ 9 ガガイモ 8 ヤブコウジ 7 セリ 6 ミクリ 5 メシダ 5
両方の科名の重複状況から考えて、品種によって…というよりも、品種の多いものが "2万5千地形図名" の欠損が多いということなのだろう。財布を落としやすい名字を調べたら、全国の名字の多い順と類似していた…といったような、まあ、妥当な欠損状況のようだ。
…と、こんな感じで Pandas を活用して、データを調べられる訳だ。
4. 歯切れの悪い終わり方だが…
まだ、調査開始したばかりで、いきなり終わるのも気が引けるが、Advent Calendar の目的が Pandas の機能調査なので、ここまでとしたい。
あわよくば "マクドナルド対コンビニの垣根を越えた戦争が始まっている" みたいなレポートが出せれば良かったのだが、そう簡単には行かない。深堀してゆくには、それなりに時間がかかる (そして、実際のデータマイニングも、こーゆー地道な作業の積み重ねだったりするのだけど) …。
今回はこんなところで。
Python で解析 23
“Advent Calendar 2013 - Python で解析!” の二十三日目。DataFrame - 16
今回は Period について。Timestamp が時刻、Period が時間を取り扱う。時間というより、期間の方が語感としては近いかもしれない。
1. Period
だいたいの言語で、日付型や時刻型は用意されているが、期間を表すオブジェクトというのは、珍しい気がする。日付型なり、時刻型なり…を使って、開始日、終了日を自分で管理するのに慣れてしまっているだけかもしれないが…。
まずは 2013 年。
In [1]: import pandas as pd In [2]: p1 = pd.Period('2013') In [3]: p1 Out[3]: Period('2013', 'A-DEC') In [4]: p1.start_time Out[4]: Timestamp('2013-01-01 00:00:00', tz=None) In [5]: p1.end_time Out[5]: Timestamp('2013-12-31 23:59:59.999999999', tz=None)
2013年1月。
In [6]: p2 = pd.Period('2013-01') In [7]: p2 Out[7]: Period('2013-01', 'M') In [8]: p2.start_time Out[8]: Timestamp('2013-01-01 00:00:00', tz=None) In [9]: p2.end_time Out[9]: Timestamp('2013-01-31 23:59:59.999999999', tz=None)
日単位や時単位の Period も作れるのだが、文字列をうまくパースしてくれない。リファレンスのサンプルには載っているのだが、やってみるとエラーが表示される。代替として、個別のパラメーターを指定して作成してみることにする。
In [10]: p3 = pd.Period(year=2013, month=12, day=24, freq='D') In [11]: p3 Out[11]: Period('2013-12-24', 'D') In [12]: p3.start_time Out[12]: Timestamp('2013-12-24 00:00:00', tz=None) In [13]: p3.end_time Out[13]: Timestamp('2013-12-24 23:59:59.999999999', tz=None)
時単位の場合。
In [14]: p4 = pd.Period(year=2013, month=12, day=24, hour=9, freq='H') In [15]: p4 Out[15]: Period('2013-12-24 09:00', 'H') In [16]: p4.start_time Out[16]: Timestamp('2013-12-24 09:00:00', tz=None) In [17]: p4.end_time Out[17]: Timestamp('2013-12-24 09:59:59.999999999', tz=None)
Period は、自由な期間 (任意の開始時刻、終了時刻) を表現することはできない。1 時間、1日、ひと月、1四半期などの、用意されている範囲で活用するもののようだ。
2. PeriodIndex
Period のリストを渡して作ってみる。
In [18]: pi1 = pd.PeriodIndex([pd.Period('2011'), pd.Period('2012'), pd.Period('2013')]) In [19]: pi1 Out[19]: <class 'pandas.tseries.period.PeriodIndex'> freq: A-DEC [2011, ..., 2013] length: 3 In [20]: type(pi1) Out[20]: pandas.tseries.period.PeriodIndex
開始、終了を指定して作ってみる。
In [21]: pi2 = pd.PeriodIndex(start='2013-1', end='2013-12', freq='M') In [22]: pi2 Out[22]: <class 'pandas.tseries.period.PeriodIndex'> freq: M [2013-01, ..., 2013-12] length: 12
月間や年間の集計などの用途で活用できそうだ。
3. 活用例
PeriodIndex を使った DataFrame を作ってみる。
In [23]: df = pd.DataFrame({ ....: 'uu': [1000, 2000, 3000, 4000, 5000, 60000] ....: }, index=pd.PeriodIndex(start='2012-10', end='2013-3', freq='M')) In [24]: df Out[24]: uu 2012-10 1000 2012-11 2000 2012-12 3000 2013-01 4000 2013-02 5000 2013-03 60000
2012 年分だけ抽出する。
In [25]: df['2012'] Out[25]: uu 2012-10 1000 2012-11 2000 2012-12 3000
2012年12月分だけ抽出する。
In [26]: df['2012-12'] Out[26]: uu 2012-12 3000
ロジックを書かずに、こーゆーことができるのが便利だ。
In [27]: df[df.index >= pd.datetime(2012, 12, 15)] Out[27]: uu 2012-12 3000 2013-01 4000 2013-02 5000 2013-03 60000
イコールを含まない場合はこうなる。
In [28]: df[df.index > pd.datetime(2012, 12, 15)] Out[28]: uu 2013-01 4000 2013-02 5000 2013-03 60000
直感的な振る舞いではない気もするが、妥当な振る舞いのような気もする。ま、どちらかと言えば、事例のフィルター条件があまりよろしくないので、実際に活用する場合は、分かりやすいフィルター条件を心がけたいところ。
今回はこんなところで。
Python で解析 22
“Advent Calendar 2013 - Python で解析!” の二十二日目。DataFrame - 15
今回はカテゴリーデータの扱いについて。カテゴリーデータというのは大きさを表す数字ではなく、種類を表すもので、例えばどのブラウザからのアクセスが多いか? のような時に活用する。
1. データの準備
では、いつもの通りのデータの準備を。
In [1]: import pandas as pd In [2]: df = pd.DataFrame({ ...: 'accessed': ['2013-12-21', '2013-12-21', '2013-12-21', '2013-12-22', '2013-12-22'], ...: 'user_id': [14600, 29000, 8800, 12100, 14600], ...: 'browser': ['IE', 'IE', 'Safari', 'Chrome', 'IE'] ...: }) In [3]: df Out[3]: accessed browser user_id 0 2013-12-21 IE 14600 1 2013-12-21 IE 29000 2 2013-12-21 Safari 8800 3 2013-12-22 Chrome 12100 4 2013-12-22 IE 14600
2. value_counts
カテゴリーデータの数を数える時は value_counts を使う。まずは、ブラウザ別。
In [4]: df.browser.value_counts() Out[4]: IE 3 Safari 1 Chrome 1 dtype: int64
次は日別。
In [5]: df.accessed.value_counts() Out[5]: 2013-12-21 3 2013-12-22 2 dtype: int64
そして、日毎のブラウザ別。
In [6]: df.groupby('accessed').browser.value_counts() Out[6]: accessed 2013-12-21 IE 2 Safari 1 2013-12-22 IE 1 Chrome 1 dtype: int64
3. stack, unstack
日毎のブラウザ別のヤツは、数が多くなって来ると、どのブラウザのアクセスが多いのか? とか、増加傾向にあるのか、減少傾向にあるのか? といったことが見づらくなる。そこで、ブラウザをカラムにして、見やすくしたい…という場合は unstack を使う。
In [7]: df.groupby('accessed').browser.value_counts().unstack() Out[7]: Chrome IE Safari accessed 2013-12-21 NaN 2 1 2013-12-22 1 1 NaN
unstack の逆は stack で、実は、元のデータを stack 表示することもできる。
In [8]: df.stack() Out[8]: 0 accessed 2013-12-21 browser IE user_id 14600 1 accessed 2013-12-21 browser IE user_id 29000 2 accessed 2013-12-21 browser Safari user_id 8800 3 accessed 2013-12-22 browser Chrome user_id 12100 4 accessed 2013-12-22 browser IE user_id 14600 dtype: object
stack <-> unstack は DataFrame <-> Series の相互変換になっていて、 Series にする時には SQL でいうところの複合キーが生成されている。
In [9]: df.stack().index Out[9]: MultiIndex [(0, u'accessed'), (0, u'browser'), (0, u'user_id'), (1, u'accessed'), (1, u'browser'), (1, u'user_id'), (2, u'accessed'), (2, u'browser'), (2, u'user_id'), (3, u'accessed'), (3, u'browser'), (3, u'user_id'), (4, u'accessed'), (4, u'browser'), (4, u'user_id')]
カラムが第二キーなっているのが分かる。
今回はこんなところで。
Python で解析 21
“Advent Calendar 2013 - Python で解析!” の二十一日目。DatetimeIndex
今回は DatetimeIndex について。
1. データの生成
DatetimeIndex を生成するには、 date_range を使う。試しに DatetimeIndex を使った DataFrame を生成してみる。
In [1]: import pandas as pd In [2]: df1 = pd.DataFrame({ ...: 'value': range(18), ...: }, index=pd.date_range('2012/9/1', '2013/8/31', freq='3W')) In [3]: df1 Out[3]: value 2012-09-02 0 2012-09-23 1 2012-10-14 2 2012-11-04 3 2012-11-25 4 2012-12-16 5 2013-01-06 6 2013-01-27 7 2013-02-17 8 2013-03-10 9 2013-03-31 10 2013-04-21 11 2013-05-12 12 2013-06-02 13 2013-06-23 14 2013-07-14 15 2013-08-04 16 2013-08-25 17
2. date_range の説明
date_range だけを実行してみると、次のようになる。
In [4]: pd.date_range('2012/9/1', '2013/8/31', freq='3W') Out[4]: <class 'pandas.tseries.index.DatetimeIndex'> [2012-09-02 00:00:00, ..., 2013-08-25 00:00:00] Length: 18, Freq: 3W-SUN, Timezone: None
DatetimeIndex が返って来る。指定するのは開始、終了、頻度で、上の例だと 2012/9/1 から 2013/8/31 までの範囲で三週間毎の Timestamp 生成を指定していることになる。 freq は省略可能。
In [5]: pd.date_range('2012/9/1', '2013/8/31') Out[5]: <class 'pandas.tseries.index.DatetimeIndex'> [2012-09-01 00:00:00, ..., 2013-08-31 00:00:00] Length: 365, Freq: D, Timezone: None
省略時は 'D' (日毎) の Timestamp が生成されることが Length が 365 になっていることから分かる。freq には週毎 'W'、時間毎 'H'、 12 時間毎 '12H' …などなど、いろいろ指定でき、月末日 'BM' なんかも便利そうだ。
タイムゾーンも指定できる。
In [6]: pd.date_range('2012/9/1', '2013/8/31', tz='Asia/Tokyo')[0] Out[6]: Timestamp('2012-09-01 00:00:00+0900', tz='Asia/Tokyo')
3. 便利なフィルター
DatetimeIndex を使うと、こんなことができる。
In [7]: df1['2012'] Out[7]: value 2012-09-02 0 2012-09-23 1 2012-10-14 2 2012-11-04 3 2012-11-25 4 2012-12-16 5
最初に作った DataFrame 中から 2012 年のものだけを抽出できた。 2013 年分も同様に抽出できるし、ある月のものを抽出することも簡単だ。
In [8]: df1['2013-03'] Out[8]: value 2013-03-10 9 2013-03-31 10
"date >= '2013/3/1' and date < '2013/4/1'" のような条件文を書かなくていいのは、なかなか便利だ。
今回はこんなところで。
Python で解析 20
“Advent Calendar 2013 - Python で解析!” の二十日目。Timestamp
今回は Timestamp について。 Python の datetime と同等と思われるが、 Pandas では Timestamp を使うようだ。効率がいいらしいが、詳しいことは未調査。まずは、使い方を。
1. Timestamp の生成
いつもなら、データの準備から始まるところだが、今回はなし。
早速 Timestamp を生成してみる。
In [1]: import pandas as pd In [2]: import datetime In [3]: from datetime import timedelta In [4]: ts = pd.Timestamp('2013/12/4') In [5]: ts Out[5]: Timestamp('2013-12-04 00:00:00', tz=None)
外国風の書式でも OK 。
In [6]: ts = pd.Timestamp('12/4/2013') In [7]: ts Out[7]: Timestamp('2013-12-04 00:00:00', tz=None)
区切りのない数字の羅列も認識する。
In [8]: ts = pd.Timestamp('20131204') In [9]: ts Out[9]: Timestamp('2013-12-04 00:00:00', tz=None)
datetime からの変換も受け付けてくれる。
In [10]: ts = pd.Timestamp(datetime.datetime(2013, 12, 4)) In [11]: ts Out[11]: Timestamp('2013-12-04 00:00:00', tz=None)
2. タイムゾーンの設定
In [12]: ts = pd.Timestamp('2013/12/4', tz='UTC') In [13]: ts Out[13]: Timestamp('2013-12-04 00:00:00+0000', tz='UTC')
日本時間は東京を指定する。
In [14]: ts = pd.Timestamp('2013/12/4', tz='Asia/Tokyo') In [15]: ts Out[15]: Timestamp('2013-12-04 00:00:00+0900', tz='Asia/Tokyo')
3. タイムゾーンの変換
タイムゾーンを持ってるなら、当然、変換ができる。必要のない人も少なくないと思われるが、私は仕事の都合で不可避な立場にいる…。
In [16]: ts = pd.Timestamp('2013/12/4', tz='UTC') In [17]: ts.tz_convert('Asia/Tokyo') Out[17]: Timestamp('2013-12-04 09:00:00+0900', tz='Asia/Tokyo')
逆もしかり。
In [18]: ts = pd.Timestamp('2013/12/4', tz='Asia/Tokyo') In [19]: ts.tz_convert('UTC') Out[19]: Timestamp('2013-12-03 15:00:00+0000', tz='UTC')
4. Timestamp の演算
演算してみた。
In [20]: pd.Timestamp('2013/12/1') - pd.Timestamp('2013/11/3') Out[20]: datetime.timedelta(28)
timedelta が返ってきた。それなら 60 日前を求めるのは timedelta を使うに違いない。
In [21]: pd.Timestamp('2013/12/1') - timedelta(days=60) Out[21]: datetime.datetime(2013, 10, 2, 0, 0)
datetime が返ってきた。
5. その他、日付関連
datetime を継承しているのかもしれないが、datetime のメソッドは一通り持っている。
In [22]: '{}/{}/{}'.format(ts.year, ts.month, ts.day) Out[22]: '2013/12/4'
datetime にないものも。
In [23]: '{} days {} quarter'.format(ts.dayofyear, ts.quarter) Out[23]: '337 days 4 quarter'
標準の datetime や date を取得することもできる。
In [24]: ts.to_datetime() Out[24]: datetime.datetime(2013, 12, 4, 0, 0, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
In [25]: ts.date() Out[25]: datetime.date(2013, 12, 4)
今回はこんなところで。
Python で解析 19
“Advent Calendar 2013 - Python で解析!” の十九日目。DataFrame - 14
今回は sort を取り上げる。だいたい想像している通りのことができる。
1. データの準備
では、いつもの通りのデータの準備を。
In [1]: import pandas as pd In [2]: df = pd.DataFrame({ ...: u'1_睦月': [18100, 22000, 6800, 14100], ...: u'2_如月': [14600, 29000, 8800, 12100], ...: u'3_弥生': [9900, 12000, 12000, 8500] ...: }, index = [u'山田', u'鈴木', u'佐藤', u'木村']) In [3]: df Out[3]: 1_睦月 2_如月 3_弥生 山田 18100 14600 9900 鈴木 22000 29000 12000 佐藤 6800 8800 12000 木村 14100 12100 8500
2. index で並び替え
引数なしでソートすると、 index でのソートになる。
In [4]: df.sort() Out[4]: 1_睦月 2_如月 3_弥生 佐藤 6800 8800 12000 山田 18100 14600 9900 木村 14100 12100 8500 鈴木 22000 29000 12000
漢字の場合、文字コード順で並び替えることは実用的ではないので、ふりがななどの適切なデータを使うところだが、あえて漢字で実験してみた。
なお、明示的に index を指定しない場合は、シーケンス番号が index として振られるので、sort() を呼び出しても何も起こらない。
3, 指定したカラムで並び替え
カラムを指定したソートは次の通り。
In [5]: df.sort(u'3_弥生') Out[5]: 1_睦月 2_如月 3_弥生 木村 14100 12100 8500 山田 18100 14600 9900 鈴木 22000 29000 12000 佐藤 6800 8800 12000
複数のカラムを指定することもできる。
In [6]: df.sort([u'3_弥生', u'2_如月']) Out[6]: 1_睦月 2_如月 3_弥生 木村 14100 12100 8500 山田 18100 14600 9900 佐藤 6800 8800 12000 鈴木 22000 29000 12000
3, 指定したカラムで降順で並び替え
デフォルトでは昇順だが、降順も指定できる。
In [7]: df.sort(u'3_弥生', ascending=False) Out[7]: 1_睦月 2_如月 3_弥生 佐藤 6800 8800 12000 鈴木 22000 29000 12000 山田 18100 14600 9900 木村 14100 12100 8500
複数のカラムで、昇順と降順を混在させることもできる。
In [8]: df.sort([u'3_弥生', u'2_如月'], ascending=[True, False]) Out[8]: 1_睦月 2_如月 3_弥生 木村 14100 12100 8500 山田 18100 14600 9900 鈴木 22000 29000 12000 佐藤 6800 8800 12000
4, 列の並び替え
axis を指定すれば、列の並び替えもできる。
In [9]: df.sort(axis=1, ascending=False) Out[9]: 3_弥生 2_如月 1_睦月 山田 9900 14600 18100 鈴木 12000 29000 22000 佐藤 12000 8800 6800 木村 8500 12100 14100
axis は 0 が縦方向、 1 が横方向を意味する。
axis を使わずに、こんなやり方もできる。
In [10]: df.T.sort(ascending=False).T Out[10]: 3_弥生 2_如月 1_睦月 山田 9900 14600 18100 鈴木 12000 29000 22000 佐藤 12000 8800 6800 木村 8500 12100 14100
今回はこんなところで。