【问题标题】:return slice of multi-indexed dataframe based on index length (hierarchical indexing)根据索引长度返回多索引数据帧的切片(分层索引)
【发布时间】:2015-01-02 07:16:02
【问题描述】:

我有一个数据框fal_mean,其中的多索引是'lat''lon''yr'。下面只是数据的一个 sn-p,但我需要做的是根据给定 lat/lon 组合的索引“yr”(年)的条目数来选择数据。例如,我只想选择每个经纬度组合的数据,其中有 N 个或更多条目(年度数据),这样len(fal_mean['yr'] >= N)

lat lon yr        101      102        103        104     105     109                                                             
35  -75 1978   410.63   410.63   1231.890   4516.950    0.00    0.00   
        1979     0.00   406.05   4060.460   6090.690  406.05    0.00   
        1980  1441.89   720.94  11535.100  12256.050    0.00    0.00   
        1982   121.54     0.00    850.790      0.000    0.00    0.00   
        1983   638.82  2874.68  37272.955   1916.455    0.00  638.82   

' 我可以根据 lat 和 lon 组合为我需要的任何列单独选择数据:

fal_mean.loc[(35, -75), '101']
Out[74]: 
yr
1978     410.630000
1979       0.000000
1980    1441.890000
1982     121.540000
1983     638.820000
1984    5419.645000
1985      99.836667
1986    7113.757500
1987       0.000000
1988       0.000000
1997     408.410000
1998     251.690000
2001     208.040000
2002       0.000000
2004       0.000000
2005       0.000000
2006       0.000000
2007       0.000000
2009       0.000000
2010       0.000000
2011       0.000000
Name: 101, dtype: float64

并获得该选择的长度:

len(fal_mean.loc[(35, -75), '101'])
Out[75]: 21

但我不知道如何使用
len(fal_mean.loc[(35, -75), '101']) > N

返回数据帧的一部分

类似:

fal_mean.loc[(len(fal_mean.loc[(35, -75), '101']) > 32)] 

除了我需要传递 lat 和 lon 索引的所有值。


编辑 1

这是一个包含每个组合长度(index=lat,columns=lon)的数据帧,所以我只需要能够在原始数据帧“fal_mean”上使用一些切片符号来调用这些组合 >N

我使用以下方法创建了数据框:

cv=np.arange(35, 45, 1)
cv2=np.arange(-75, -66, 1)
fal=pd.DataFrame(data=None, index=cv, columns=cv2)
for lat in cv:
    for lon in cv2:
        fal.loc[lat, lon]=len(fal_mean.xs((lat, lon), level=('lat', 'lon')))

    -75 -74 -73 -72 -71 -70 -69 -68 -67
35  21  8   0   0   0   0   0   0   0
36  33  32  0   0   0   0   0   0   0
37  33  35  0   0   0   0   0   0   0
38  13  35  32  8   0   0   0   0   0
39  0   31  35  35  25  9   16  0   0
40  0   0   35  32  36  37  37  37  37
41  0   0   0   0   34  33  36  37  37
42  0   0   0   0   0   37  37  35  37
43  0   0   0   0   0   32  35  31  34
44  0   0   0   0   0   0   0   12  31

我希望有一些聪明的切片符号可以用来做这件事。我试过xsdf.index.get_level_values 但我的语法是错误的。

例如fal_mean.loc[:, len(fal_mean.index.get_level_values('yr') >32)] 不起作用。

如果没有办法在一行中执行此操作,我可以在此矩阵上调用一个布尔数组,并希望使用.loc 为原始组合中的这些组合调用 0 和 1 索引(纬度、经度)数据框,但我还不确定如何去做。

fal >=32

    -75     -74     -73     -72     -71     -70     -69     -68     -67
35  False   False   False   False   False   False   False   False   False
36  True    True    False   False   False   False   False   False   False
37  True    True    False   False   False   False   False   False   False
38  False   True    True    False   False   False   False   False   False
39  False   False   True    True    False   False   False   False   False
40  False   False   True    True    True    True    True    True    True
41  False   False   False   False   True    True    True    True    True
42  False   False   False   False   False   True    True    True    True
43  False   False   False   False   False   True    True    False   True
44  False   False   False   False   False   False   False   False   False

编辑 2: 这是前 50 行和 4 列,有 28+ 列,但这并不重要。我想将所有列仅保留在纬度和经度组合中,并且年份索引至少有 (N) 个条目 - 我认为 32 可能就足够了。使用上面的数据框作为指导,这将排除经纬度组合 (35, (all)), (36, -74), (38, -75) 等中的数据。

这些数据是由 groupby 函数 grouped=nm.groupby(['lat', 'lon', 'yr']) 生成的,所以如果我可以使用一些限制器修改该调用,以得到 grouped.year 的结果长度,那也可以。我试过df.groupby(['key1', 'key2', 'key3']).size(),这给出了每年被分箱到每个纬度组合的数据点数。

                       101          102            103           104  
lat lon yr                                                             
35  -75 1978    410.630000   410.630000    1231.890000   4516.950000   
        1979      0.000000   406.050000    4060.460000   6090.690000   
        1980   1441.890000   720.940000   11535.100000  12256.050000   
        1982    121.540000     0.000000     850.790000      0.000000   
        1983    638.820000  2874.680000   37272.955000   1916.455000   
        1984   5419.645000   516.155000   12778.280000     96.990000   
        1985     99.836667     0.000000    2819.083333  13977.286667   
        1986   7113.757500  3909.402500   10313.850000   2823.675000   
        1987      0.000000   708.610000    6841.430000      0.000000   
        1988      0.000000     0.000000    4711.750000      0.000000   
        1997    408.410000   204.210000       0.000000      0.000000   
        1998    251.690000     0.000000   13507.510000      0.000000   
        2001    208.040000   485.420000   17474.970000      0.000000   
        2002      0.000000     0.000000    2173.193333      0.000000   
        2004      0.000000     0.000000       0.000000    465.480000   
        2005      0.000000     0.000000     231.600000      0.000000   
        2006      0.000000     0.000000    1209.420000      0.000000   
        2007      0.000000     0.000000       0.000000      0.000000   
        2009      0.000000     0.000000    3561.485000      0.000000   
        2010      0.000000     0.000000     347.500000      0.000000   
        2011      0.000000     0.000000    4742.660000      0.000000   
    -74 1994    908.000000   113.500000    1589.000000      0.000000   
        1996    231.960000     0.000000   55207.410000      0.000000   
        1999  18414.830000   575.460000  142139.500000    575.460000   
        2000      0.000000     0.000000   19388.510000    842.980000   
        2003   4654.030000     0.000000    2694.440000      0.000000   
        2005   6229.700000  1245.940000    8098.600000      0.000000   
        2006   3294.950000  6243.060000   14740.550000    346.840000   
        2013  19512.960000  9420.050000   10261.130000      0.000000   
36  -75 1977    426.498667   612.972667    5114.548667   6870.683333   
        1978    213.488571  1339.422857    7686.621429  12274.601429   
        1979    140.881333   536.751333    5403.046000   7349.630667   
        1980   3669.234667   552.227333   68924.586000   6117.865333   
        1981     24.875455   322.680909    6340.275455  22119.756364   
        1982   9261.615714  3890.987143   16226.872857    122.911429   
        1983    199.143333   478.403333   70658.200476    524.357143   
        1984   8193.242857   996.810714   43920.052143   3900.735714   
        1985    514.931364    23.260455    8051.927727    924.295909   
        1986   2884.836667  4156.231667   23677.898000   1393.353667   
        1987   2555.915417  2792.415000   25936.742917    833.030833   
        1988   1410.285000  1159.560000    7141.306667      0.000000   
        1993   6952.696667  9823.026667   64672.390000   5508.930000   
        1994    214.590000     0.000000  127691.851429   4720.532857   
        1995      0.000000     0.000000    3534.124000      0.000000   
        1996      0.000000     0.000000   63118.047500      0.000000   
        1997    175.766000   421.272000   23034.918000    527.300000   
        1998    105.652000     0.000000    2508.806000      0.000000   
        1999      0.000000     0.000000    1245.455000      0.000000   
        2000      0.000000     0.000000   10889.758000      0.000000   
        2001    948.245000   441.873750   27449.827500    138.930000   

【问题讨论】:

  • 我曾使用 xs 创建矩阵并刚刚编辑了问题以显示我的代码,但我仍然不确定如何在一行中获取我需要的数据作为切片。就像我说的,我可以找到长度,我可以找到值,但是我找不到某个长度的值。我可能不得不使用另一个循环来做到这一点,但我希望有更简单的东西。感谢您的评论。

标签: python pandas indexing multi-index


【解决方案1】:

为了 SO,这是我最终得到的解决方案。不,我没有找到优雅的单行解决方案,我不得不使用循环。但它可以完成工作。

# remove lat lon combinations where total sample years are less than Num
Num=32 # set criteria ~ 2014-1977 = 37 -5 ->32
def remove_N (nm, cv, cv2): # remove lat lon combinations where total sample years are less than N
    nm['id']=-1
    ll_index=0
    keep = list()
    for lat in cv:
        for lon in cv2:
            if len(nm.xs((lat, lon), level=('lat', 'lon'))) == 0:
                continue
            if len(nm.xs((lat, lon), level=('lat', 'lon'))) >= Num: # N
                keep.append(ll_index)
            t = nm.loc[lat,lon]
            t.id = ll_index
            ll_index = ll_index + 1
        data = nm.ix[nm ['id'].isin(keep)]
    data=data.drop('id', 1)
    return(data)

【讨论】:

    【解决方案2】:

    我不确定是否能正确理解您的问题。 您想拥有超过 30 年条目的所有 [lat,lon] 组合吗?

    如果是这样,你可能会使用类似的东西

    many_years = df[df.groupby(level=[0,1,2])['101'].count()>=30]
    

    如果您可以提供数据框的最小示例,我可以尝试提供更好的帮助,理想情况下,我们可以通过 ipython 中的 pd.read_clipboard() 导入,并获得您想要的结果。

    【讨论】:

    • 我在上面的编辑中添加了更多数据。是的,这就是我所追求的。我的 groupby 函数有一个 .count 输出,但它产生了包含在该 lat,lon bin 中的样本数量,这些样本数量是当年一起平均的。我将样本分箱到 1 度的箱中,并采取每年的平均值。我只能使用大部分完整的记录(每个位置 > 32 年)。
    • 好的,经过一番挖掘,如果我可以将列表传递给行选择器,xs 可能会工作。类似df.xs(({lat_list},), level='lat', ({lon_list},), level='lon')[:]
    • 或者不...我需要 lat 和 lon 的组合,因此分别传递 lats 和 lons 列表作为键不会删除任何东西...
    猜你喜欢
    • 2022-11-03
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多