融化唯一索引的panda数据帧,以便与ggplot/rpy2一起使用



这个问题与(在Python panda中拆分和连接数据帧以使用rpy2进行绘图(有关。我正在处理pandas数据帧,并对它们进行各种融化/解融化/连接操作,这样我就可以使用rpy2用ggplot2绘制它们。对于如何对具有唯一索引的数据帧执行这些操作,我有点困惑。假设数据帧df有一个唯一的列runner_id,它记录每个跑步者完成两个比赛(比赛AB(之一的时间和速度。每个流道都是唯一的,因此对于两个流道bobmary,DataFrame可以具有这种形状:

df = pandas.DataFrame([{"runner_id": "bob", "time_A": 30,
                        "time_B": 25, "speed_A": 5, "speed_B": 10},
                       {"runner_id": "mary", "time_A": 29,
                        "time_B": 19, "speed_A": 8, "speed_B": 12}])

df看起来像这样:

  runner_id  speed_A  speed_B  time_A  time_B
0       bob        5       10      30      25
1      mary        8       12      29      19

由于运行程序是唯一的,因此对数据帧runner_id进行索引非常方便。它还防止意外添加重复条目,因为我们知道每个跑步者的所有信息都应该保存在跑步者的行中,并且我们不能每个跑步者有多行:

df = df.set_index("runner_id")

问题是,如果我们想绘制两次比赛之间的时间或速度差异,ggplot需要使用列名time_A, time_B, speed_A, speed_B中的信息。那么df需要看起来像这样:

runner_id  race  time  speed 
bob        A     ...   ...
mary       A     
bob        B
mary       B

这样我们就可以做到:

ggplot2.ggplot(df) + 
ggplot2.geom_point(aes_string(x="time", y="speed", colour="race")) ...

尽管这违反了runner_id条目的唯一性,因为运行者需要重复。一般来说,如何处理这一问题?有没有一种好的形式可以保持df,它允许唯一的索引,但也可以方便地表示ggplot?我觉得在这两者之间来回切换很困难/很困惑。第一种按跑者索引的每场比赛具有不同时间/速度列的表示非常直观,而ggplot的融化表示令人困惑,似乎很浪费。

任何关于在这两者之间来回转换的想法,或者关于如何保持数据帧的一般规则,都会有所帮助。在使用ggplot时,答案是否不是索引(不调用set_index(?这类数据帧有首选格式吗?

一个潜在的解决方案是在未熔化/熔化时始终索引/取消索引df,如:

melted_df = pandas.melt(df.reset_index(), id_vars="runner_id")

但这似乎容易出错。例如,如果我想计算每个跑步者在A比赛中的速度和时间的平均值,我可以尝试列出A条目:

# This is already complicated
a_entries = melted_df[map(lambda x: x.endswith("_A"), melted_df["variable"])]

我知道有多余/熔化的表示,所以很难进行不重复计算跑步者的操作,因为每个跑步者现在出现两次:

  runner_id variable  value
0       bob  speed_A      5
1      mary  speed_A      8
4       bob   time_A     30
5      mary   time_A     29

熔化和铸造数据帧是R.Hadley的程序包reshape中的常见操作(发现原始melt()reshape2之所以流行是有原因的(。

使用ggplot2,还可以将数据添加到图层中的绘图中。举个例子:

import rpy2.robjects.pandas2ri
rpy2.robjects.pandas2ri.activate()
p = ggplot2.ggplot(rpy2.robjects.conversion.py2ri(df)) + 
    ggplot2.geom_point(ggplot2.aes_string(x="time_A",y="speed_A"),colour="#ff0000") + 
    ggplot2.geom_point(ggplot2.aes_string(x="time_B",y="speed_B"),colour="#0000ff") + 
    ggplot2.scale_x_continuous("time") + 
    ggplot2.scale_y_continuous("speed")
p.plot()

对一个长问题的简短而迟来的回答:您似乎可以使用一些帮助来理解长格式数据帧。每个值都是唯一的,因为每场比赛只有一个具有给定名称的"跑步者"。它一开始可以融化你的大脑,但它非常强大,对于利用ggplot2的功能至关重要。Hadley Wickham在几篇文章中很好地解释了这一点,例如:http://had.co.nz/reshape/paper-dsc2005.pdf‎

最新更新