Pandas中的多维/嵌套DataFrame/Dataset/Panel

3
我希望能在pandas dataframe或panel中存储一些多维数据,以便能够返回例如以下内容:
  1. Runner A、Race A的所有时间
  2. 2015年Race A的所有时间(和名称)
示例数据如下,注意并非所有选手都有所有年份或所有比赛的数据。
请问有没有人能够建议一种使用Pandas或其他方式来实现这个目标的好方法?
Name     | Gender | Age
Runner A | Male   | 35
    Race A
        Year | Time     
        2015 | 2:35:09  
        2014 | 2:47:34
        2013 | 2:50:12
    Race B
        Year | Time
        2013 | 1:32:07

Runner B | Male | 29
    Race A
        Year | Time
        2015 | 3:05:56

Runner C | Female | 32
    Race B
        Year | Time
        1998 | 1:29:43

1
我不明白为什么这需要多重索引,为什么不能将Runner作为列,年份和比赛呢? - EdChum
谢谢@EdChum,那可能仍然是最好的选择,但我试图避免在每一行中存储所有跑步者个人资料数据(例如性别、年龄等)。 - Danwise
年龄是指比赛运行时的具体年龄还是选手当前的状态? - piRSquared
@Danwise - 我认为最好的方法是创建一个新问题,而不是更新它 - 因为我认为更新问题与之前太不同了。这可行吗? - jezrael
谢谢@jezrael,我会这样做。 - Danwise
显示剩余2条评论
2个回答

4

我认为您可以使用Multiindex,然后通过切片器选择数据:

import pandas as pd

df = pd.DataFrame({'Time': {('Runner A', 'Male', 35, 'Race A', 2014): '2:47:34', ('Runner C', 'Female', 32, 'Race B', 1998): '1:29:43', ('Runner B', 'Male', 29, 'Race A', 2015): '3:05:56', ('Runner A', 'Male', 35, 'Race A', 2013): '2:50:12', ('Runner A', 'Male', 35, 'Race B', 2013): '1:32:07', ('Runner A', 'Male', 35, 'Race A', 2015): '2:35:09'}})
print (df)
                                   Time
Runner A Male   35 Race A 2013  2:50:12
                          2014  2:47:34
                          2015  2:35:09
                   Race B 2013  1:32:07
Runner B Male   29 Race A 2015  3:05:56
Runner C Female 32 Race B 1998  1:29:43

#index has to be fully lexsorted
df.sort_index(inplace=True)
print (df)
                                   Time
Runner A Male   35 Race A 2013  2:50:12
                          2014  2:47:34
                          2015  2:35:09
                   Race B 2013  1:32:07
Runner B Male   29 Race A 2015  3:05:56
Runner C Female 32 Race B 1998  1:29:43

idx = pd.IndexSlice
print (df.loc[idx['Runner A',:,:,'Race A',:],:])
                                 Time
Runner A Male 35 Race A 2013  2:50:12
                        2014  2:47:34
                        2015  2:35:09

print (df.loc[idx[:,:,:,'Race A',2015],:])
                                 Time
Runner A Male 35 Race A 2015  2:35:09
Runner B Male 29 Race A 2015  3:05:56

2

简单方法:

runners = pd.DataFrame(
    [
        ['Bob',   'Male', 1980],
        ['Tom',   'Male', 1986],
        ['Amy', 'Female', 1966],
    ],
    columns=['Name', 'Gender', 'BirthYear']
)

races = pd.DataFrame(
    [
        ['A', 2015, 'Bob', '2:35:09'],
        ['A', 2014, 'Bob', '2:47:34'],
        ['A', 2013, 'Bob', '2:50:12'],
        ['B', 2013, 'Bob', '1:32:07'],
        ['A', 2015, 'Tom', '3:05:56'],
        ['B', 1998, 'Amy', '1:29:43'],
    ],
    columns=['Race', 'Year', 'Name', 'Time']
)


print races.loc[(races.Name == 'Bob') & (races.Race == 'A')][['Time']]
print 
print races.loc[(races.Year == 2015) & (races.Race == 'A')][['Name', 'Time']]

      Time
0  2:35:09
1  2:47:34
2  2:50:12

  Name     Time
0  Bob  2:35:09
4  Tom  3:05:56

获取所有数据

df = races.merge(runners)

获取比赛时的年龄

df['Age'] = df.Year - df.BirthYear
print df

  Race  Year Name     Time  Gender  BirthYear  Age
0    A  2015  Bob  2:35:09    Male       1980   35
1    A  2014  Bob  2:47:34    Male       1980   34
2    A  2013  Bob  2:50:12    Male       1980   33
3    B  2013  Bob  1:32:07    Male       1980   33
4    A  2015  Tom  3:05:56    Male       1986   29
5    B  1998  Amy  1:29:43  Female       1966   32

谢谢@piRSquared,我试图避免在每一行中存储所有的跑步者个人资料数据(例如性别、年龄等),但这仍然可能是一个选项。 - Danwise
@Danwise 已经明白了。我会发布其他内容。 - piRSquared
@piRSquared - 请查看评论 - jezrael
这个有效,谢谢。我如何传递多个多维数组? - Andrey Kurnikovs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接