【问题标题】:for loop in dataframe in pandas熊猫数据框中的for循环
【发布时间】:2022-01-08 04:11:34
【问题描述】:

我在使用 pandas 数据框的“for 循环”时遇到问题,希望有人能提供帮助。

我在 csv 文件中有以下数据框:

,forename,surname,gender,age,100m,200m,400m,800m,1500m
0,Migdalia,Parrish,F,18,11.08,29.0,59.41,122.05,259.11
1,Valerie,Lee,F,10,17.23,46.0,100.02,232.64,480.95
2,John,Debnam,M,17,10.81,25.89,50.6,110.29,232.39
3,Roy,Miller,M,10,19.18,46.74,95.32,201.14,430.27
4,Aida,Aumiller,F,11,15.3,41.83,81.06,189.03,394.9
5,Marcia,Brown,F,19,11.13,24.62,57.59,119.13,256.37
6,Harry,Knows,M,16,12.39,25.94,49.67,106.56,237.14
7,Barry,Lennon,M,14,11.15,23.56,46.46,110.89,230.49
8,Lilia,Armstrong,F,13,8.84,25.09,59.54,128.95,258.47
9,Johnny,Casey,M,15,9.65,22.67,49.46,112.85,233.87
10,Donald,Taylor,M,15,11.74,22.42,49.22,114.62,224.63
11,Martha,Woods,F,14,9.01,24.34,55.25,118.8,254.87
12,Diane,Lauria,F,15,8.99,27.92,54.79,119.89,249.21
13,Yvonne,Pumphrey,F,16,8.84,27.29,57.63,123.13,247.41
14,Betty,Stephenson,F,14,11.04,28.73,59.05,126.29,256.44
15,Lilia,Armstrong,F,12,11.31,34.43,74.28,150.05,321.07

我必须创建一个调用另一个函数的主函数,该函数使用“for 循环”检索每个年龄 (10,11,12,13,14,15,16) 时间最快的运动员特定的性别(例如“F”)和距离(例如“100m”)。

例如:

Input:
fastest_athletes = find_fastest_athletes(df,"100m","F",[10,11,12,13,14,15,16])
Output:
{
10: {’forename’: 'Valerie’, 'surname’: 'Lee’, 'time’: '17.23’},
11: {’forename’: 'Aida’, 'surname’: 'Aumiller’, 'time’: '15.3’},
12: {’forename’: 'Lilia’, 'surname’: 'Armstrong’, 'time’: '11.31’},
13: {’forename’: 'Lilia’, 'surname’: 'Armstrong’, 'time’: '8.84’},
14: {’forename’: 'Martha’, 'surname’: 'Woods’, 'time’: '9.01’},
15: {’forename’: 'Diane’, 'surname’: 'Lauria’, 'time’: '8.99’},
16: {’forename’: 'Yvonne’, 'surname’: 'Pumphrey’, 'time’: '8.84’}
}

我做了以下代码:

# Function with the for loop
def find_fastest_athletes(df,distance,gender,ages):
  for age in range(10,16):
    fastest_athletes = df[(df["gender"] == gender) & (df["age"] == age)]
    fastest_athletes_sorted = fastest_athletes.sort_values(distance,ascending=True)
    fastest_athletes_value = fastest_athletes_sorted.iloc[[0]][["forename","surname","100m"]]
    athletes_data = fastest_athletes_value.to_string(index=False, header=False).split('  ')
    athletes_data_dict = {
        'forename': athletes_data[0].strip(),
        'surname': athletes_data[1],
        'time': float(athletes_data[2])
        }
  return athletes_data_dict
  
# Main function
def main(filename='athletes.csv'):
    df = pd.read_csv(filename, index_col=0)
    df['100m'] = df['100m'].astype(float)
    print(find_fastest_athletes(df,'100m','F',[10,11,12,13,14,15,16]))
    return
   
if __name__ == "__main__":
  main()  

通过我的编码,我得到的输出只有上一个年龄段(16 岁)的最快运动员,而不是每个年龄段(10、11、12、13、14、15、16)的所有最快运动员,为什么那个?

另外如何在每行的开头添加年龄?

【问题讨论】:

    标签: pandas dataframe for-loop


    【解决方案1】:

    最简单的答案是,当您想要的只是一个分组时,您不应该执行复杂的功能。我不知道为什么你的代码不起作用。

    # Melt into a long-form dataframe
    df_long = df.melt(id_vars=['forename', 'surname', 'gender', 'age'], var_name='event', value_name='time')
    
    # Get the indices for maximum times in each gender/age/event and then use those indices to get the original rows
    df_fastest = df_long.iloc[df_long.groupby(['gender', 'age', 'event'])['time'].idxmax(), :]
    

    对于一个事件:

    >>> df_fastest.loc[df_fastest['event'] == '100m', :]
    
        forename    surname gender  age event   time
    1   Valerie Lee F   10  100m    17.23
    4   Aida    Aumiller    F   11  100m    15.30
    15  Lilia   Armstrong   F   12  100m    11.31
    ...
    

    【讨论】:

    • 谢谢,我试过了,但它看起来返回完整列表,而不是推断每个年龄(10、11、12、13、14、15、16)时间最快的运动员特定性别“F”和距离“100m”。但是,如果我想用 for 循环保留函数,你看到我的代码哪里出错了吗?我认为这是一件小事,但无法解决,谢谢!
    • 它告诉你每个性别、年龄、项目组合的最快时间的运动员。似乎它正在返回所有内容,因为您的示例数据只有 F14 和 M15 出现多次。如果你想选择一个特定的事件,你可以很容易地做到这一点。您的代码不是以容易发现技术缺陷的方式编写的。
    【解决方案2】:

    我认为您的代码仅返回上一个时代最快的运动员的原因 是因为您一直在覆盖变量 athletes_data_dict-

     def find_fastest_athletes(df,distance,gender,ages):
       tmp = []
       for age in ages:
         fastest_athletes = df.loc[(df.gender == gender) & (df.age == age)]
    
         fastest_athletes_sorted = fastest_athletes.sort_values(distance,ascending=True)
    
         fastest_athletes_value = fastest_athletes_sorted.iloc[[0]][["forename","surname","100m"]]
         athletes_data = fastest_athletes_value.to_string(index=False, header=False).split('  ')
         athletes_data_dict = {
        'forename': athletes_data[0].strip(),
        'surname': athletes_data[1],
        'time': float(athletes_data[2])
        }
        tmp.append(athletes_data_dict)
    return tmp
    

    我还更改了数据框的切片以及循环中的范围。 所以我用一个列表来存储所有的值,对我来说效果很好。

    【讨论】:

    • 非常感谢您的帮助,非常感谢。我相应地重写了代码并且它有效!顺便说一句:只是一件小事:现在我将所有 7 个输出放在一行中,当我附加数据时,如何将它们放在 7 个单独的行中?当使用“追加”但没有成功时,我查看了整个互联网以找到正确的命令以转到下一行。
    • 是的,我也看了,也许你可以试试这个: res = '\n'.join(str(line) for line in tmp) 如果你的函数在return语句之前,你可以替换'return tmp' 与这个变量。它会将时间字段转换为字符串。
    猜你喜欢
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-11
    相关资源
    最近更新 更多