【问题标题】:Loop only takes last value循环只取最后一个值
【发布时间】:2019-08-01 06:47:08
【问题描述】:

我有一个包含每年特定国家人口的数据框和一个包含每年世界人口的熊猫系列。 这是我正在使用的系列:

pop_tot = df3.groupby('Year')['population'].sum()
Year     
1990    4.575442e+09
1991    4.659075e+09
1992    4.699921e+09
1993    4.795129e+09
1994    4.862547e+09
1995    4.949902e+09
...     ...
2017    6.837429e+09

这是我正在使用的 DataFrame

        Country      Year   HDI     population
0       Afghanistan 1990    NaN     1.22491e+07
1       Albania     1990    0.645   3.28654e+06
2       Algeria     1990    0.577   2.59124e+07
3       Andorra     1990    NaN     54509
4       Angola      1990    NaN     1.21714e+07
...     ...         ...     ...     ...
4096    Uzbekistan  2017    0.71    3.23872e+07 
4097    Vanuatu     2017    0.603   276244  
4098    Zambia      2017    0.588   1.70941e+07 
4099    Zimbabwe    2017    0.535   1.65299e+07 

我想计算每年该国人口占世界人口的比例,所以我循环遍历Series和DataFrame,如下所示:

j = 0
for i in range(len(df3)):
    if df3.iloc[i,1]==pop_tot.index[j]:
        df3['pop_tot']=pop_tot[j] #Sanity check
        df3['weighted']=df3['population']/pop_tot[j]
        *df3.iloc[i,2]
    else:
        j=j+1 

但是,我得到的 DataFrame 不是预期的。我最终将所有值除以 2017 年的总人口,从而给了我当年不正确的比例(即对于第一行,pop_tot 应该是 4.575442e+09,因为它对应于 1990 年根据系列上面而不是对应于 2017 年的 6.837429e+09)。

     Country   Year HDI   population  pop_tot      weighted
  0  Albania   1990 0.645 3.28654e+06 6.837429e+09 0.000257158
  1  Algeria   1990 0.577 2.59124e+07 6.837429e+09 0.00202753
  2  Argentina 1990 0.704 3.27297e+07 6.837429e+09 0.00256096

但是我看不出循环中有什么错误。 提前致谢。

【问题讨论】:

    标签: python pandas loops


    【解决方案1】:

    你不需要循环,你可以使用groupby.transform直接在df3中创建列pop_tot。那么对于列weighted只需做列操作,如:

    df3['pop_tot'] = df3.groupby('Year')['population'].transform(sum)
    df3['weighted'] = df3['population']/df3['pop_tot']
    

    正如@roganjosh 指出的那样,您的方法的问题在于,每次满足条件if 时,您都会替换整个列pop_totweighted,因此在满足此条件的最后一次迭代中,年份可能是 2017 年,您将 pop_tot 列的值定义为 2017 年的值,并使用该值计算加权。

    【讨论】:

    • 他们的循环不起作用,因为他们在每次迭代时都引用了整个列
    • 谢谢,这是解决问题的更好方法
    • @Daniel 这样会比使用循环更快for :)
    • 谢谢,我现在也看到了循环的问题
    【解决方案2】:

    您不必循环,它的速度较慢,并且可以使事情变得非常复杂。例如,使用 pandasnumpys 这样的矢量化解决方案:

    df['pop_tot'] = df.population.sum()
    df['weighted'] =  df.population / df.population.sum()
    
    print(df)
           Country  Year    HDI  population     pop_tot  weighted
    0  Afghanistan  1990    NaN  12249100.0  53673949.0  0.228213
    1      Albania  1990  0.645   3286540.0  53673949.0  0.061232
    2      Algeria  1990  0.577  25912400.0  53673949.0  0.482774
    3      Andorra  1990    NaN     54509.0  53673949.0  0.001016
    4       Angola  1990    NaN  12171400.0  53673949.0  0.226766
    

    在 OP 发表评论后编辑

    df['pop_tot'] = df.groupby('Year').population.transform('sum')
    
    df['weighted'] =  df.population / df['pop_tot']
    
    print(df)
           Country  Year    HDI  population     pop_tot  weighted
    0  Afghanistan  1990    NaN  12249100.0  53673949.0  0.228213
    1      Albania  1990  0.645   3286540.0  53673949.0  0.061232
    2      Algeria  1990  0.577  25912400.0  53673949.0  0.482774
    3      Andorra  1990    NaN     54509.0  53673949.0  0.001016
    4       Angola  1990    NaN  12171400.0  53673949.0  0.226766
    

    注意
    我以您提供的小数据集为例:

        Country     Year    HDI     population
    0   Afghanistan 1990    NaN     12249100.0
    1   Albania     1990    0.645   3286540.0
    2   Algeria     1990    0.577   25912400.0
    3   Andorra     1990    NaN     54509.0
    4   Angola      1990    NaN     12171400.0
    

    【讨论】:

    • 谢谢,但在这种情况下,我不确定您是否会特定年份,因为 df3.population.sum() 将汇总人口列中的所有值,而不管年份如何。我将编辑示例以使其更清晰。
    • 我明白了,对我的原始答案进行了编辑,但这与 Ben.T 现在的答案基本相同,所以你应该接受那个。 @丹尼尔
    猜你喜欢
    • 2015-04-08
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 2021-12-27
    • 2021-11-13
    相关资源
    最近更新 更多