【问题标题】:Finding the largest difference in population among multiple counties?在多个县之间找到最大的人口差异?
【发布时间】:2017-01-26 16:48:28
【问题描述】:

我正在 python 上学习 pandas,似乎无法完成这个问题。有 6 个人口列,POPESTIMATE2010 到 POPESTIMATE 2016,我需要找到这些年之间人口变化最大的县。 (例如,如果 5 年期间的县人口为 100、120、80、105、100、130,则其在该期间的最大变化将是 |130-80| = 50。)

到目前为止我所做的是设法将数据操作到数组和列表中,但我不确定哪个更好地解决这个问题:

import numpy as np
def answer_seven():
    sumlev = census_df.SUMLEV.values == 50
    data = census_df[['POPESTIMATE2010', 'POPESTIMATE2011','POPESTIMATE2012','POPESTIMATE2013','POPESTIMATE2014','POPESTIMATE2015', 'CTYNAME']].values[sumlev]
    s = pd.Series(data[:, 0], [data[:, 1], data[:, 2], data[:, 3], data[:, 4], data[:, 5], data[:, 6]], dtype=np.int64)
return data
answer_seven()

返回数据时的输出:

array([[54660, 55253, 55175, ..., 55290, 55347, 'Autauga County'],
   [183193, 186659, 190396, ..., 199713, 203709, 'Baldwin County'],
   [27341, 27226, 27159, ..., 26815, 26489, 'Barbour County'],
   ..., 
   [21102, 20912, 20989, ..., 20903, 20822, 'Uinta County'],
   [8545, 8469, 8443, ..., 8316, 8328, 'Washakie County'],
   [7181, 7114, 7065, ..., 7185, 7234, 'Weston County']], dtype=object)

当我返回 s 列表时,我会得到一个列表:

55253   55175   55038   55290   55347   Autauga County         54660
186659  190396  195126  199713  203709  Baldwin County        183193
27226   27159   26973   26815   26489   Barbour County         27341
22733   22642   22512   22549   22583   Bibb County            22861
57711   57776   57734   57658   57673   Blount County          57373
10629   10606   10628   10829   10696   Bullock County         10887
20673   20408   20261   20276   20154   Butler County          20944
117768  117286  116575  115993  115620  Calhoun County        118437
33993   34075   34153   34052   34123   Chambers County        34098
26080   26023   26084   25995   25859   Cherokee County        25976
43739   43697   43795   43921   43943   Chilton County         43665
13593   13543   13378   13289   13170   Choctaw County         13841
25570   25144   25116   24847   24675   Clarke County          25767
13670   13456   13467   13538   13555   Clay County            13880
14971   14921   15028   15072   15018   Cleburne County        14973
50448   51173   50755   50831   51211   Coffee County          50177
54443   54472   54471   54480   54354   Colbert County         54514
13121   12996   12875   12662   12672   Conecuh County         13208
11348   11195   11059   10807   10724   Coosa County           11758
38060   37818   37830   37888   37835   Covington County       37796
13896   13951   13932   13948   13963   Crenshaw County        13853
80469   80374   80756   81221   82005   Cullman County         80473
50109   50324   49833   49501   49565   Dale County            50358
43178   42777   42021   41662   41131   Dallas County          43803
71387   70942   70869   71012   71130   DeKalb County          71142
80012   80432   80883   81022   81468   Elmore County          79465
38213   38034   37857   37784   37789   Escambia County        38309
104236  104235  103852  103452  103057  Etowah County         104442
17062   16960   16857   16842   16759   Fayette County         17231
31729   31648   31507   31592   31696   Franklin County        31734
                                                               ...  

我查看了多个论坛帖子,但找不到与此真正相关的任何内容。我知道最好的方法是创建一个“最高”列和一个“最低”列,然后找到差异最大的县,但我不知道如何在一个大批。非常感谢您的帮助!

【问题讨论】:

    标签: python arrays pandas


    【解决方案1】:

    我认为这应该可以解决您的问题

    temp = census_df[census_df['SUMLEV'] == 50].set_index('CTYNAME')
    yrs = ['POPESTIMATE2010','POPESTIMATE2011','POPESTIMATE2012','POPESTIMATE2013', 'POPESTIMATE2014', 'POPESTIMATE2015']
    res = temp.loc[:,yrs].max(axis=1) - temp.loc[:,yrs].min(axis=1)
    res.idxmax()
    

    【讨论】:

      【解决方案2】:

      鉴于您提到的数据(仅限于演示目的仅几行),让我们首先将其转换为适当的 DataFrame:

      from io import StringIO
      
      dataset = """\
      55253   55175   55038   55290   55347   Autauga County         54660
      186659  190396  195126  199713  203709  Baldwin County        183193
      27226   27159   26973   26815   26489   Barbour County         27341
      22733   22642   22512   22549   22583   Bibb County            22861
      57711   57776   57734   57658   57673   Blount County          57373
      """
      
      df = pd.DataFrame.from_csv(StringIO(dataset), sep='\s{2,}', header=None).reset_index()
      df.columns = ['y1', 'y2', 'y3', 'y4', 'y5', 'name', 'y6']
      df = df.set_index('name')
      df.head()
      
                      y1      y2      y3      y4      y5      y6
      name                        
      Autauga County  55253   55175   55038   55290   55347   54660
      Baldwin County  186659  190396  195126  199713  203709  183193
      Barbour County  27226   27159   26973   26815   26489   27341
      Bibb County     22733   22642   22512   22549   22583   22861
      Blount County   57711   57776   57734   57658   57673   57373
      

      然后你可以使用numpy的minmax方法来计算数据集中的最小值和最大值。之后,您可以创建一个包含最大差异的新 DataFrame。与 pandas 或 numpy 中的优化方法相比,python 中不需要任何慢的循环。

      df2 = DataFrame((np.max(df.values, axis=1) - np.min(df.values, axis=1)), index=df.index, columns=['largest_diff'])
      df2.head()
      
                      largest_diff
      name    
      Autauga County  687
      Baldwin County  20516
      Barbour County  852
      Bibb County     349
      Blount County   403
      

      【讨论】:

      • 数据集有几百行,不能简单的复制粘贴。感谢您的帮助-如果您能详细说明如何将您的代码集成到我编写的任何代码中以使其正常工作,我将非常感激。当我尝试使用你放的东西时,我得到'numpy.ndarray'对象没有属性'set_index'
      • 你不应该使用 StringIO。这只是为了演示如何使用 panda 的 from_csv 方法。请参阅文档。 path 参数可以是字符串文件路径或文件句柄/StringIO,因此在实际实现中无需复制粘贴。同样from_csv 返回一个DataFrame 实例,没有numpy.ndarray。因为这个set_index是定义如果使用这个方法。
      【解决方案3】:

      如果您将数据放在 pandas 数据框中,请使用 pandas min() 和 max() 方法:

      >>> df1
      year:   2010    2011    2012    2013    2014
      city                    
      abilene 47000   2000    31000   72000   47000
      boise   44000   55000   68000   17000   63000
      calgary 39000   86000   6000    97000   1000
      denver  57000   52000   46000   0       43000
      
      >>> df1.T.max()-df1.T.min()
      city
      abilene    70000
      boise      51000
      calgary    96000
      denver     57000
      dtype: int32
      

      【讨论】:

      • 这是给我整个集合中最高的数字减去整个集合中的最低数字。我需要找到每行的最高数字减去每行中的最低数字,然后是差异最大的县的名称。希望澄清
      • 使用s = (df.T.max() - df.T.min()).sort_values(ascending=False) s.name = 'diff' s.reset_index().ix[0] 找出答案中代码返回的Series中的最大值。
      • 感谢您的澄清。我输入了它,现在我收到“错误 - 无效语法”?
      • @Rich columns_to_keep = ['POPESTIMATE2015','POPESTIMATE2014','POPESTIMATE2013','POPESTIMATE2012','POPESTIMATE2011','POPESTIMATE2010'] 你能解释一下为什么你的代码给出了错误的输出吗?错误:x1=census_df[columns_to_keep]x= (x1.T.max()-x1.T.min()).argmax()return census_df.iloc[x].CTYNAME 正确:f1 = census_df.set_index(['STNAME', 'CTYNAME']).ix[:,columns_to_keep].stack()f2 = f1.max(level=['STNAME','CTYNAME']) - f1.min(level = ['STNAME', 'CTYNAME'])return f2.idxmax()[1]
      【解决方案4】:

      试试这个:

      def df_max_dif (x):
      
          max_dif = 0
      
          for ind in x.index:
      
              max_value = np.max(np.abs(x-x.loc[ind]))
      
              if max_value > max_dif:
      
                  max_dif = max_value
      
          return max_dif
      
      df['max_dif'] = np.nan
      
      for indx in df.index:
      
          df.loc[indx,'max_dif'] = df_max_dif(df.loc[indx].drop('max_dif'))
      

      希望对你有帮助!

      【讨论】:

      • 感谢您的帮助,但我到处都遇到了错误。您能否进一步解释我如何集成您的代码?我不断收到“str 和 int 不支持的操作数类型”
      • 该错误意味着您正在尝试使用不可能的字符串进行操作,很可能是 np.max() 或 x-x.loc[ind]。你必须做的就是只传递带有数值的列。
      • 我该怎么做?
      • df[['column_name1','column_name2',...]] 而不仅仅是 df。使用您要选择的列名
      【解决方案5】:

      这是我的幼稚实现。

      maxchange = (None,0)
      for row in data:
          low = min(row[:-1])
          high = max(row[:-1])
          if high-low > maxchange[1]:
              maxchange = (row[-1], high-low)
      print(maxchange)
      

      这使用在answer_seven 中创建的data 数组。这只是找到每个县的最小值和最大值,并找到县之间的最大差异。

      【讨论】:

      • 感谢您的帮助,但您的代码出现的错误是“分配前引用的局部变量 'maxchange'”。在如何集成您的代码以使其正常工作方面,我们将不胜感激
      • 对不起,忘记复制maxchange的初始化。我现在已经更新了。
      【解决方案6】:
      def my_idea():
          columns_to_keep = ['POPESTIMATE2015','POPESTIMATE2014','POPESTIMATE2013','POPESTIMATE2012','POPESTIMATE2011','POPESTIMATE2010']
          copy_df = census_df[columns_to_keep]
      
          # max_difference_per_country is a Series with sorted values from high to low
          max_difference_per_country = (copy_df.max(axis=1) - copy_df.min(axis=1)).sort_values(ascending=False)
          # get its index
          index_of_max_difference_per_country = max_difference_per_country.first_valid_index()
          return census_df['CTYNAME'].iloc[index_of_max_difference_per_country]
      

      【讨论】:

        【解决方案7】:

        @Tolis 提供的答案不排除州,并给出“德克萨斯”作为结果。正确的代码应该是这样的:

        def answer_seven():
             columns_to_keep = ['POPESTIMATE2015','POPESTIMATE2014','POPESTIMATE2013','POPESTIMATE2012','POPESTIMATE2011','POPESTIMATE2010']
             rows_to_keep = census_df[census_df['SUMLEV'] == 50]
             copy_df = rows_to_keep[columns_to_keep]
        
             # max_difference_per_country is a Series with sorted values from high to low
             max_difference_per_country = (copy_df.max(axis=1) - copy_df.min(axis=1)).sort_values(ascending=False)
        
             # get its index
             index_of_max_difference_per_country = max_difference_per_country.first_valid_index()
        
             return census_df['CTYNAME'].iloc[index_of_max_difference_per_country]
        

        【讨论】:

          【解决方案8】:
          def answer_seven():
          
              county = census_df[census_df['SUMLEV']==50]
              county= county.set_index('CTYNAME')
              req_col = ['POPESTIMATE2010',
                                     'POPESTIMATE2011',
                                     'POPESTIMATE2012',
                                     'POPESTIMATE2013',
                                     'POPESTIMATE2014',
                                     'POPESTIMATE2015']
              countyP= county[req_col]
          
              res = (countyP[req_col].max(axis=1) - countyP[req_col].min(axis=1)).nlargest(1)
          
          
              return res.argmax()
          
          answer_seven()
          
          

          【讨论】:

            【解决方案9】:

            一条线就能搞定

            def answer_seven():
            
                cols = [ 'POPESTIMATE2010','POPESTIMATE2011','POPESTIMATE2012','POPESTIMATE2013','POPESTIMATE2014','POPESTIMATE2015' ]
            
                new = census_df[ census_df['SUMLEV']==50 ].set_index('CTYNAME').apply( lambda x: np.max( x[cols]  - np.min( x[cols]) ), axis=1)
            
                return new.idxmax()
            

            【讨论】:

            • 这很简洁,但与其他解决方案相比非常慢
            【解决方案10】:
            def answer_seven():
                temp=[];
                df=census_df.groupby('STNAME')
                df=df.sum()
                val=df[['POPESTIMATE2010','POPESTIMATE2011','POPESTIMATE2012','POPESTIMATE2013','POPESTIMATE2014','POPESTIMATE2015']]
            
                max_val=val.max(axis=1)
                min_val=val.min(axis=1)
            
                fd=max_val-min_val;
                fd=fd[fd.values==fd.values.max()]
                return fd.index[0]
            

            【讨论】:

            • 简单易行
            【解决方案11】:
            def answer_seven():
                df=census_df[ census_df['SUMLEV']==50 ]
                df['Max']=df[['POPESTIMATE2010','POPESTIMATE2011','POPESTIMATE2012','POPESTIMATE2013','POPESTIMATE2014','POPESTIMATE2015']].max(axis=1)
                df['Min']=df[['POPESTIMATE2010','POPESTIMATE2011','POPESTIMATE2012','POPESTIMATE2013','POPESTIMATE2014','POPESTIMATE2015']].min(axis=1)
                df['Diff']= df['Max'] - df['Min']
            
                max_val_idx=df['Diff'].idxmax()
                return df.loc[max_val_idx]['CTYNAME']
            answer_seven()
            

            【讨论】:

            • 简单易行
            【解决方案12】:
            def answer_seven():
                max= census_df[['POPESTIMATE2010', 'POPESTIMATE2011', 'POPESTIMATE2012','POPESTIMATE2013', "POPESTIMATE2014", "POPESTIMATE2015"]].max(axis=1)
                min= census_df[['POPESTIMATE2010', 'POPESTIMATE2011', 'POPESTIMATE2012', 'POPESTIMATE2013', "POPESTIMATE2014", "POPESTIMATE2015"]].min(axis=1)
                absolute_diff = (max-min).abs()
                absolute_diff.index = census_df.index
                census_df['absolute_diff'] = absolute_diff
                return census_df.loc[census_df[census_df['SUMLEV'] == 50]['absolute_diff'].idxmax(), 'CTYNAME']
            

            【讨论】:

            • 添加一些细节会更好。
            【解决方案13】:
            def answer_seven():
                df=census_df[ census_df['SUMLEV']==50 ]
                df['STDEV']=df[['POPESTIMATE2010','POPESTIMATE2011','POPESTIMATE2012','POPESTIMATE2013','POPESTIMATE2014','POPESTIMATE2015']].std(axis=1)
                max_val_idx=df['STDEV'].idxmax()
                return df.loc[max_val_idx]['CTYNAME']
            answer_seven()
            

            【讨论】:

            • 简单易行
            猜你喜欢
            • 2012-03-08
            • 2017-04-18
            • 1970-01-01
            • 2014-11-16
            • 2012-10-17
            • 1970-01-01
            • 1970-01-01
            • 2013-03-27
            • 1970-01-01
            相关资源
            最近更新 更多