Python 在For循环中创建数据帧会产生Nan错误

Python 在For循环中创建数据帧会产生Nan错误,python,pandas,indexing,jupyter-notebook,Python,Pandas,Indexing,Jupyter Notebook,在探索Jupyter笔记本上的奥运数据集时,我试图找出哪项运动是世界上最古老的运动 这是我目前拥有的代码: 体育=奥运会。设置指数(“体育”) sport_name=olympics['sport'].unique() 对于sport_名称中的sport: 播放年份=sports.loc[sport,['Year']].max()-sports.loc[sport,['Year']].min() 印刷品(运动、比赛年限) 代码将返回以下结果: Basketball Year 80.0

在探索Jupyter笔记本上的奥运数据集时,我试图找出哪项运动是世界上最古老的运动

这是我目前拥有的代码:


体育=奥运会。设置指数(“体育”)
sport_name=olympics['sport'].unique()
对于sport_名称中的sport:
播放年份=sports.loc[sport,['Year']].max()-sports.loc[sport,['Year']].min()
印刷品(运动、比赛年限)
代码将返回以下结果:

Basketball Year    80.0
dtype: float64
Judo Year    52.0
dtype: float64
Boxing Year    112.0
dtype: float64

注意,每个浮点数前都有一个字符串“Year”

然后我尝试使用以下代码将其转换为数据帧:

sports=olympics.set_索引('Sport'))
sport_name=olympics['sport'].unique()
对于sport_名称中的sport:
播放年份=sports.loc[sport,['Year']].max()-sports.loc[sport,['Year']].min()
行=[]
rows=rows.append([运动,比赛年份])
pd.DataFrame(行、列=['Sport','Years Players'])
返回了一个错误:
KeyError:nan

我有两个问题:

  • 为什么循环在每个浮点结果之前返回字符串“Year”?我尝试在循环外使用同一行代码(使用
    .loc
    ,然后用
    .min()
    减去
    .max()
    ),结果之前没有字符串,只有结果的浮点数
  • 是什么导致了
    nan
    错误

  • 非常感谢。

    你好,kim,欢迎来到StackOverflow。我会尽力解释得更好

    问题1 循环将以以下格式返回结果:

    dtype: int64
    Basque Pelota Year    0
    
    dtype: int64
    Aeronautics 0
    
    如您所见,巴斯克佩洛塔第0个年头包含
    第0个年头
    ,但
    航空第0个年头
    没有

    在第一种情况下,播放的
    年份类型为
    ,但在第二种情况下为
    。这意味着在第一种情况下,您必须访问序列的值,如:
    years\u player['Year']
    ,但在第二种情况下,如果您尝试此操作,将引发异常
    indexer:invalid index to scalar variable.
    ,因为它是
    int64
    类型而不是序列

    在您的情况下,检查所播放的
    年份的类型并根据类型获取值就足够了:

    print(sport, years_played['Year'] if isinstance(years_played, Series) else years_played)
    
    请查看参考资料以获取。还可以使用反正避免使用
    type()
    ,因为它只返回对象的类型,而如果对象参数是classinfo参数或其(直接、间接或虚拟)子类的实例,则
    isinstance()
    返回
    true

    最终代码 基本上,最终代码将产生如下结果:

    import pandas as pd
    from pandas.core.series import Series
    
    olympics = pd.read_csv("athlete_events.csv")
    
    sports = olympics.set_index('Sport')
    sport_name = olympics['Sport'].unique()
    
    for sport in sport_name:
        years_played = sports.loc[sport, ['Year']].max() - sports.loc[sport, ['Year']].min()
        print(type(years_played)) 
        print(sport, years_played['Year'] if isinstance(years_played, Series) else years_played)
    
    解决问题的另一种方法是在开始时解决类型问题:

    import pandas as pd
    from pandas.core.series import Series
    
    olympics = pd.read_csv(r"C:\Users\carlo.zanocco\Desktop\archive\athlete_events.csv")
    
    sports = olympics.set_index('Sport')
    sport_name = olympics['Sport'].unique()
    
    for sport in sport_name:
        years_played = sports.loc[sport, 'Year'].max() - sports.loc[sport, 'Year'].min()
        print(type(years_played)) 
        print(sport, years_played)
    
    在这里,我将
    sports.loc[sport,['Year']].max()-sports.loc[sport,['Year'].min()
    更改为
    sports.loc[sport,['Year'].max()-sports.loc[sport,['Year']].min()
    ,因此它将只返回类型为
    的值,并且打印结果时不需要检查类型

    问题2 错误
    KeyError:nan
    表示您试图访问一个不存在的密钥。在您的情况下,键
    nan


    从本质上说,这个异常映射到找不到的键。

    天哪,我可以理解为什么调试起来很困难。输出屏幕截图中缺少的是最后一部分

    Year    80
    dtype: int64
    Year    52
    dtype: int64
    ...
    Year    12
    dtype: int64
    Year    0
    dtype: int64
    0
    
    请注意最后一行如何不遵循其余行的模式!如果您在循环结束时检查
    sport
    years\u play
    ,则没有任何问题。但是如果你检查

    • sports.loc[sport[0],'Year']
    • sports.loc[sport[-1],'Year']
    比较一下,你就会知道发生了什么

    第一个是数据帧。您将看到它被一个名为
    Sport
    的索引索引,其中的每个条目都是
    Basketball
    。像这样:

                Year
    Sport           
    Basketball  1992
    Basketball  2008
    Basketball  1952
    Basketball  2000
    Basketball  1972
    ...          ...
    Basketball  2004
    Basketball  1996
    Basketball  2004
    Basketball  2008
    Basketball  2016
    
    [4536 rows x 1 columns]
    
    然而,第二个是一个系列:

    Year    1936
    Name: Aeronautics, dtype: object
    
    sports.loc[sport, 'Year'] ->
    
    Sport
    Basketball    1992
    Basketball    2008
    Basketball    1952
    Basketball    2000
    Basketball    1972
                  ... 
    Basketball    2004
    Basketball    1996
    Basketball    2004
    Basketball    2008
    Basketball    2016
    Name: Year, Length: 4536, dtype: int64
    
    。。。如果您只从数据帧中选择一行,则得到的结果

    我怀疑您已经知道了这一点-我注意到您将
    'Year'
    包装在一个列表中,这确保您在第一种情况下获得一个数据帧。只有一列称为“年”,因此如果不这样做,您将返回一个系列:

    Year    1936
    Name: Aeronautics, dtype: object
    
    sports.loc[sport, 'Year'] ->
    
    Sport
    Basketball    1992
    Basketball    2008
    Basketball    1952
    Basketball    2000
    Basketball    1972
                  ... 
    Basketball    2004
    Basketball    1996
    Basketball    2004
    Basketball    2008
    Basketball    2016
    Name: Year, Length: 4536, dtype: int64
    
    (找出与先前输出的差异)

    现在,如果你做
    sports.loc[“Aeronautics”,“Year”]
    你只需要返回一个整数,
    1936
    ,因为你选择了一个单元格。这将导致错误,因为
    int
    没有代码所期望的
    max
    min
    方法

    一种解决方案是强制它总是返回一个数据帧。你可以这样做

    用于运动名称中的运动:
    data=sports.loc[[sport],'Year']]
    播放年份=data.max()-data.min()
    印刷品(运动、比赛年限)
    
    。。。但这只是让问题的真正原因显而易见,而不是解决问题。现在
    data.max()-data.min()
    返回

    Year    0
    dtype: int64
    
    这是一个熊猫系列,只有一个条目。该系列的索引是
    “Year”
    (因为这是上面创建的数据框
    数据的列名)。这就是你得到奇怪输出的原因。实际的解决方法很简单-只需选择单个值,现在我们已经确保始终可以得到一个系列:

    用于运动名称中的运动:
    data=sports.loc[[sport],'Year']]
    播放年份=data.max()-data.min()
    打印(运动,玩了多少年[0])
    

    您发布的第二段代码永远不会起作用:

    用于运动名称中的运动:
    播放年份=sports.loc[sport,['Year']].max()-sports.loc[sport,['Year']].min()
    行=[]
    rows=rows.append([运动,比赛年份])
    pd.DataFrame(行、列=['Sport','Years Players'])
    
    最后一行从您已创建的单行创建一个新的数据帧