使用列子集的匹配长度裁剪数据框列

时间:2019-03-22 16:57:19

标签: python pandas

我有一个数据框,其中包含来自多个站点的年度数据。在每个站点内,有多个数据源,这些数据源的年数并不相等。我不知道提前几年的上下限,并且每个站点的上下限都不同。

我的数据如下:

Year    Site    Source    Value
1880     1         A       1.2
1881     1         A       1.4
1882     1         A       2.1
1883     1         A       2.7
1881     1         B       1.3
1882     1         B       1.8
1883     1         B       1.4
1891     2         A       1.9
1892     2         A       2.0
1893     2         A       2.1
1892     2         B       2.4
1893     2         B       2.2

对于每个站点,我想使用时间跨度最短的源来裁剪数据,以便数据看起来像这样:

Year    Site    Source    Value
1881     1         A       1.4
1882     1         A       2.1
1883     1         A       2.7
1881     1         B       1.3
1882     1         B       1.8
1883     1         B       1.4
1892     2         A       2.0
1893     2         A       2.1
1892     2         B       2.4
1893     2         B       2.2  

到目前为止我的尝试:

for site in df['Site'].unique():

    A = df[df['Source'] == 'A']
    B = df[df['Source'] == 'B']

    if len(A['Year']) < len(B['Year']):
        B['Year'] = B.clip(A['Year'].min, A.['Year'].max)

    if len(B['Year']) < len(A['Year'):
        A['Year'] = A.clip(B['Year'].min, B['Year'].max)

    df[df['Source'] == 'A'] = A
    B = df[df['Source'] == 'B']

产生:

Year    Site    Source    Value
1881     1         A       1.4
1882     1         A       2.1
1883     1         A       2.7
1881     1         B       1.3
1882     1         B       1.8
1883     1         B       1.4
1881     2         A       1.4
1882     2         A       2.1
1883     2         A       2.7
1881     2         B       1.3
1882     2         B       1.8
1883     2         B       1.4  

1 个答案:

答案 0 :(得分:1)

由于这些站点是独立的,因此可以在groupby中使用它们的功能,与您的外循环类似。

您可以编写一个处理每个站点的函数,删除超出重叠范围的行:

def filter_site(site):
    # look at the lowest year for each source,
    # take the max value of them as lower bound
    lower = site.groupby("Source").Year.min().max()

    # likewise for upper bound
    upper = site.groupby("Source").Year.max().min()

    # filter with lower and upper bound
    return site[(site.Year >= lower) & (site.Year <= upper)]

然后在所有站点上应用该功能:

df.groupby("Site", group_keys=False).apply(filter_site)