Python /熊猫:条件求和

时间:2020-09-11 15:26:38

标签: python pandas conditional-statements

我正在处理大型数据集,并且无法为以下任务的条件编码:

以下是与我自己的问题类似的示例。我正在尝试计算物质在介质中传播的速度。每年,对于每个标识,都会将一种物质插入介质中。目的是计算每次插入的“到达年”。每年每种物质在每种介质中的传播距离以[%]计算。

我的数据集类似于以下内容:

import pandas as pd
ids = [1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3]
year= [2000,2001,2002,2003,2004,2005,2000,2001,2002,2003,2004,2005,2000,2001,2002,2003,2004,2005]
traveldistance = [120,70,37,40,50,110,140,100,90,5,52,80,60,40,70,60,50,110]

dictex ={"id":ids,"year of insertion":year,"travel distance [%]": traveldistance}
dfex = pd.DataFrame(dictex)

print(dfex)
    medium id  year of insertion  travel distance [%]
0           1               2000                  120
1           1               2001                   70
2           1               2002                   37
3           1               2003                   40
4           1               2004                   50
5           1               2005                  110
6           2               2000                  140
7           2               2001                  100
8           2               2002                   90
9           2               2003                    5
10          2               2004                   52
11          2               2005                   80
12          3               2000                   60
13          3               2001                   40
14          3               2002                   70
15          3               2003                   60
16          3               2004                   50
17          3               2005                  110

要考虑以下几个条件:

  1. 一种物质在其插入介质的那一年就不能开始传播(即,一种在2000年插入的物质只能在2001年开始传播)。因此,在此示例中,2005年插入的物质无法在观察的时间范围内到达目的地。
  2. 到达年份是通过加上以下年份的行驶距离[%]来计算的。一旦达到> = 100%的传播距离,该物质便到达了介质另一侧的目的地。该年是到达的年份,应在新列中添加。
  3. 如果在观察到的时间内旅行距离未达到100%,则结果应为[NaN]

示例:

a)对于媒介id == 1,插入的第一年是2000年。该物质于2001年开始传播,并传播了70%的媒介。在2002年,它又移动了37%:70 + 37 = 107%> = 100%,因此第一种物质的到达年份是2002年。

b)在2001年,第二种物质插入介质id ==1。它在2002年开始传播,并通过37%的介质。在2003年,它又移动了40%:37 + 40 = 77%<100% 2004年,该物质通过50%的介质传播:37 + 40 + 50 = 127%> = 100%,因此第二种物质的到达年份为2004年。

结果应如下所示:

     medium id  year of insertion  travel distance [%]  Year of arrival
0           1               2000                  120           2002.0
1           1               2001                   70           2004.0
2           1               2002                   37           2005.0
3           1               2003                   40           2005.0
4           1               2004                   50           2005.0
5           1               2005                  110              NaN
6           2               2000                  140           2001.0
7           2               2001                  100           2004.0
8           2               2002                   90           2005.0
9           2               2003                    5           2005.0
10          2               2004                   52              NaN
11          2               2005                   80              NaN
12          3               2000                   60           2002.0
13          3               2001                   40           2003.0
14          3               2002                   70           2004.0
15          3               2003                   60           2005.0
16          3               2004                   50           2005.0
17          3               2005                  110              NaN

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

我不知道针对此特定情况的任何内置熊猫方法。但这是apply和一些numpy处理的解决方案。

def rolling_fwd_idx_over(df, group_by_cols, value_col, target_col, cutoff=100):
    def find_cross(group):
        travel = group[value_col].to_numpy()
        travel = np.broadcast_to(travel, (travel.size, travel.size))
        travel = np.triu(travel, 1).cumsum(axis=1)
        idx = np.argmax(travel >= cutoff, axis=1)
        out = np.where(
            travel[range(travel.shape[0]), idx] >= cutoff,
            group[target_col].to_numpy()[idx],
            np.nan
        )
        return out
    
    df['result'] = (
        df.groupby(group_by_cols).apply(find_cross).explode()
            .reset_index(drop=True)
    )
    return df

用作

dfex = rolling_fwd_idx_over(
    dfex, 'id', 'travel distance [%]', 'year of insertion')
dfex.rename(columns={'result': 'Year of arrival'}, inplace=True)

输出

    id  year of insertion  travel distance [%] Year of arrival
0    1               2000                  120            2002
1    1               2001                   70            2004
2    1               2002                   37            2005
3    1               2003                   40            2005
4    1               2004                   50            2005
5    1               2005                  110             NaN
6    2               2000                  140            2001
7    2               2001                  100            2004
8    2               2002                   90            2005
9    2               2003                    5            2005
10   2               2004                   52             NaN
11   2               2005                   80             NaN
12   3               2000                   60            2002
13   3               2001                   40            2003
14   3               2002                   70            2004
15   3               2003                   60            2005
16   3               2004                   50            2005
17   3               2005                  110             NaN