我有所有棒球运动员的国家,开始和结束的年份。我需要知道每个国家/地区每年有多少名球员

时间:2019-03-22 18:29:07

标签: python pandas

我有一个拥有20,000名玩家的数据集。列为birthCountry,debut_year和final_year。

    birthCountry debut_year  final_year
0   USA          2004        2015
1   USA          1954        1976
2   USA          1962        1971
3   USA          1977        1990
4   USA          2001        2006

我需要获取如下表格:

              1980 1981 1982
    USA         50   49   48   
    CANADA      XX   XX   XX  
    MEXICO      XX   XX   XX
    ...

其中每个单元代表当年在特定国家/地区出生的球员数量。

我创建了一个嵌套列表,其中包含每个玩家玩过的所有年份。此列表的长度与df的长度相同。在df中,我每年创建一列,然后尝试为每个玩家/年份组合添加1。

想法是使用它来创建groupby或ivot_table

# create a list of years
years = list(range(min(df['debut_year'].values),max(df['final_year'].values)+1))

# create a list of countries
countries = df.birthCountry.unique()

# add columns for years
for n in range(1841,2019): #years are from 1841 to 2018
    df[n] = ''
# now I have one additional column for every year. A lot of new empty columns

# temporary lists
templist = list(range(0,len(df)))

# every element of the following list contains all the years each player played
templist2 = []
for i in templist:
    templist2.append(list(range(int(df.iloc[i,1]),int(df.iloc[i,2])))) 

# add 1 if the player played that year
for i in range(len(df)):
    for j in templist2[i]:
        df.iloc[i][j] = 1

我跑了一段时间,然后在原始数据框中没有任何变化。

可能您会找到更好,更优雅的解决方案。

2 个答案:

答案 0 :(得分:3)

为了限制示例的大小,我创建了以下源DataFrame:

df = pd.DataFrame(data=[[ 1, 'USA', 1974, 1978 ], [ 2, 'USA', 1976, 1981 ],
    [ 3, 'USA', 1975, 1979 ], [ 4, 'USA', 1977, 1980 ],
    [ 5, 'Mex', 1976, 1979 ], [ 6, 'Mex', 1978, 1980 ]],
    columns=['Id', 'birthCountry', 'debut_year', 'final_year'])

实际计算的第一步是创建一个 Series 每个玩家活跃的年份:

years = df.apply(lambda row: pd.Series(range(row.debut_year,
    row.final_year + 1)), axis=1).stack().astype(int).rename('year')

第二步是创建一个辅助DataFrame-连接 df.birthCountryyears

df2 = df[['birthCountry']].join(years.reset_index(level=1, drop=True))

最后一步是产生实际结果:

df2.groupby(['birthCountry', 'year']).size().rename('Count')\
    .unstack().fillna(0, downcast='infer')

对于以上测试数据,结果为:

year          1974  1975  1976  1977  1978  1979  1980  1981
birthCountry                                                
Mex              0     0     1     1     2     2     1     0
USA              1     2     3     4     4     3     2     1

我认为,我的解决方案比之前提出的其他解决方案更具“泛音”感 由 Remy

答案 1 :(得分:1)

如果我正确理解您的df变量的结构,便可以提出以下解决方案。我为示例创建了一个具有相同结构的字典列表(使用较小的年份范围):

df = [{'birthCountry': 'USA', 'debut_year': 2012, 'final_year': 2016},
      {'birthCountry': 'CANADA', 'debut_year': 2010, 'final_year': 2016},
      {'birthCountry': 'USA', 'debut_year': 2012, 'final_year': 2017},
      {'birthCountry': 'CANADA', 'debut_year': 2012, 'final_year': 2017},
      {'birthCountry': 'MEXICO', 'debut_year': 2012, 'final_year': 2016}]

countries = {}
for field in df:
    if field['birthCountry'] not in countries.keys():
        countries[field['birthCountry']] = {year: 0 for year in range(2010, 2019)}
    for year in range(field['debut_year'], field['final_year']):
        countries[field['birthCountry']][year] += 1