python柱形图显示年份_关于python:Pandas:按日历周分组,然后绘制真实日期时间的分组条形图...

编辑

我找到了一个很好的解决方案,并将其发布在下面作为答案。

结果将如下所示:

J0BXc.png

您可以针对此问题生成一些示例数据:

1

2

3

4

5codes = list('ABCDEFGH');

dates = pd.Series(pd.date_range('2013-11-01', '2014-01-31'));

dates = dates.append(dates)

dates.sort()

df = pd.DataFrame({'amount': np.random.randint(1, 10, dates.size), 'col1': np.random.choice(codes, dates.size), 'col2': np.random.choice(codes, dates.size), 'date': dates})

导致:

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

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66In [55]: df

Out[55]:

amount col1 col2 date

0 1 D E 2013-11-01

0 5 E B 2013-11-01

1 5 G A 2013-11-02

1 7 D H 2013-11-02

2 5 E G 2013-11-03

2 4 H G 2013-11-03

3 7 A F 2013-11-04

3 3 A A 2013-11-04

4 1 E G 2013-11-05

4 7 D C 2013-11-05

5 5 C A 2013-11-06

5 7 H F 2013-11-06

6 1 G B 2013-11-07

6 8 D A 2013-11-07

7 1 B H 2013-11-08

7 8 F H 2013-11-08

8 3 A E 2013-11-09

8 1 H D 2013-11-09

9 3 B D 2013-11-10

9 1 H G 2013-11-10

10 6 E E 2013-11-11

10 6 F E 2013-11-11

11 2 G B 2013-11-12

11 5 H H 2013-11-12

12 5 F G 2013-11-13

12 5 G B 2013-11-13

13 8 H B 2013-11-14

13 6 G F 2013-11-14

14 9 F C 2013-11-15

14 4 H A 2013-11-15

.. ... ... ... ...

77 9 A B 2014-01-17

77 7 E B 2014-01-17

78 4 F E 2014-01-18

78 6 B E 2014-01-18

79 6 A H 2014-01-19

79 3 G D 2014-01-19

80 7 E E 2014-01-20

80 6 G C 2014-01-20

81 9 H G 2014-01-21

81 9 C B 2014-01-21

82 2 D D 2014-01-22

82 7 D A 2014-01-22

83 6 G B 2014-01-23

83 1 A G 2014-01-23

84 9 B D 2014-01-24

84 7 G D 2014-01-24

85 7 A F 2014-01-25

85 9 B H 2014-01-25

86 9 C D 2014-01-26

86 5 E B 2014-01-26

87 3 C H 2014-01-27

87 7 F D 2014-01-27

88 3 D G 2014-01-28

88 4 A D 2014-01-28

89 2 F A 2014-01-29

89 8 D A 2014-01-29

90 1 A G 2014-01-30

90 6 C A 2014-01-30

91 6 H C 2014-01-31

91 2 G F 2014-01-31

[184 rows x 4 columns]

我想按日历周和col1值分组。像这样:

1

2kw = lambda x: x.isocalendar()[1]

grouped = df.groupby([df['date'].map(kw), 'col1'], sort=False).agg({'amount': 'sum'})

导致:

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

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67In [58]: grouped

Out[58]:

amount

date col1

44 D 8

E 10

G 5

H 4

45 D 15

E 1

G 1

H 9

A 13

C 5

B 4

F 8

46 E 7

G 13

H 17

B 9

F 23

47 G 14

H 4

A 40

C 7

B 16

F 13

48 D 7

E 16

G 9

H 2

A 7

C 7

B 2

... ...

1 H 14

A 14

B 15

F 19

2 D 13

H 13

A 13

B 10

F 32

3 D 8

E 18

G 3

H 6

A 30

C 9

B 6

F 5

4 D 9

E 12

G 19

H 9

A 8

C 18

B 18

5 D 11

G 2

H 6

A 5

C 9

F 9

[87 rows x 1 columns]

然后,我想像这样生成图:

rsfmn.png

这意味着:x轴上的日历周和年份(日期时间),每个分组的col1都为一个小节。

我面临的问题是:我只有整数来描述日历周(图中的KW),但是我必须以某种方式将其上的日期合并回去,以使年份也标记为刻度。此外,我不能仅绘制日历周,因为我需要正确排列项目的顺序(kw 47,kw 48(2013年)必须在kw 1的左侧(因为这是2014年))。

编辑

我从这里想通了:

http://pandas.pydata.org/pandas-docs/stable/visualization.html#visualization-barplot分组的条需要是列而不是行。因此,我考虑了如何转换数据,并发现了pivot方法,该方法非常有用。需要reset_index才能将多索引转换为列。最后,我用零填充NaN:

1A = grouped.reset_index().pivot(index='date', columns='col1', values='amount').fillna(0)

将数据转换为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16col1 A B C D E F G H

date

1 4 31 0 0 0 18 13 8

2 0 12 13 22 1 17 0 8

3 3 10 4 13 12 8 7 6

4 17 0 10 7 0 25 7 4

5 7 0 7 9 8 6 0 7

44 0 0 2 11 7 0 0 2

45 9 3 2 14 0 16 21 2

46 0 14 7 2 17 13 11 8

47 5 13 0 15 19 7 5 10

48 15 8 12 2 20 4 7 6

49 20 0 0 18 22 17 11 0

50 7 11 8 6 5 6 13 10

51 8 26 0 0 5 5 16 9

52 8 13 7 5 4 10 0 11

看起来像文档中的示例数据以分组的条形图所示:

1A. plot(kind='bar')

得到这个:

uDozx.png

而我现在对轴进行排序(从1-52开始)时出现问题,这实际上是错误的,因为在这种情况下,日历周52属于2013年...关于如何合并实际日期时间的任何想法日历周并将其用作x轴刻度?

评论应该真的在评论中。 我知道在没有足够多的人回答问题时很容易灰心,但是最好的做法是从问题中删除不相关的部分,并尽力使问题尽可能地直截了当。

真的,那不是评论。 只是给用户的信息,对所有读者都非常有帮助...

我认为resample('W')是执行此操作的更好方法-默认情况下,它按在星期日结束的几周进行分组(" W"与" W-SUN"相同),但是您可以指定所需的内容。

在您的示例中,请尝试以下操作:

1

2

3

4

5

6

7

8

9

10

11

12

13grouped = (df

.groupby('col1')

.apply(lambda g: # work on groups of col1

g.set_index('date')

[['amount']]

.resample('W', how='sum') # sum the amount field across weeks

)

.unstack(level=0) # pivot the col1 index rows to columns

.fillna(0)

)

grouped.columns=grouped.columns.droplevel() # drop the 'col1' part of the multi-index column names

print grouped

grouped.plot(kind='bar')

它将打印您的数据表并绘制与您相似的图,但带有"真实"日期标签:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16col1 A B C D E F G H

date

2013-11-03 18 0 9 0 8 0 0 4

2013-11-10 4 11 0 1 16 2 15 2

2013-11-17 10 14 19 8 13 6 9 8

2013-11-24 10 13 13 0 0 13 15 10

2013-12-01 6 3 19 8 8 17 8 12

2013-12-08 5 15 5 7 12 0 11 8

2013-12-15 8 6 11 11 0 16 6 14

2013-12-22 16 3 13 8 8 11 15 0

2013-12-29 1 3 6 10 7 7 17 15

2014-01-05 12 7 10 11 6 0 1 12

2014-01-12 13 0 17 0 23 0 10 12

2014-01-19 10 9 2 3 8 1 18 3

2014-01-26 24 9 8 1 19 10 0 3

2014-02-02 1 6 16 0 0 10 8 13

好吧,我终于回答了这个问题。关键不是按日历周分组(因为您会丢失有关年份的信息),而是按包含日历周和年份的字符串分组。

然后使用pivot更改问题中已经提到的布局(重塑)。日期将作为索引。使用reset_index()将当前date -index设为一列,而是获取一个整数范围作为索引(然后以正确的顺序绘制(最低年/日历周为索引0,最高年/日历周是最高整数)。

选择date列作为新变量ticks作为列表,然后从DataFrame中删除该列。现在绘制条形图,并将xticks的标签设置为ticks。完整的解决方案非常简单,这里:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15codes = list('ABCDEFGH');

dates = pd.Series(pd.date_range('2013-11-01', '2014-01-31'));

dates = dates.append(dates)

dates.sort()

df = pd.DataFrame({'amount': np.random.randint(1, 10, dates.size), 'col1': np.random.choice(codes, dates.size), 'col2': np.random.choice(codes, dates.size), 'date': dates})

kw = lambda x: x.isocalendar()[1];

kw_year = lambda x: str(x.year) + ' - ' + str(x.isocalendar()[1])

grouped = df.groupby([df['date'].map(kw_year), 'col1'], sort=False, as_index=False).agg({'amount': 'sum'})

A = grouped.pivot(index='date', columns='col1', values='amount').fillna(0).reset_index()

ticks = A.date.values.tolist()

del A['date']

ax = A.plot(kind='bar')

ax.set_xticklabels(ticks)

结果:

J0BXc.png

哇,非常好,简单,干净的解决方案。 我喜欢。 关于matplotlib-axisticks没有太多麻烦:)

将星期加到一年中的52次,以便按"年"排序星期。将对勾标签设置回您想要的位置,这可能是不平凡的。

你想要的是像这样增加几周

1nth week → (n+1)th week → (n+2)th week → etc.

但是当您有新的一年时,它下降了51(52 → 1)。

为了弥补这一点,请注意,年份增加了一年。因此,将当年的增长乘以52即可得出总变化为-51 + 52 = 1。

"将一周增加到一年中的52次"是什么意思? 当我按日历周分组时,日期时间丢失了,这对于我的绘图是需要的:(

又名 不要按周分组,按week + 52*year分组。 尽管要注意第365天...

不知何故我还是不明白。 但是也许我不得不重新思考一下,为什么要加上一年中的52的倍数以按返回值分组

嗯,现在我明白了,您的意思是delta_year * 52具有自开始以来的实际周数。

是。 年份从2013年左右开始并不重要,因为这只会使数字更大(而不是两者之间的差异)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值