【问题标题】:Python/ Pandas: Conditional summationPython/ Pandas:条件求和
【发布时间】:2020-09-11 15:26:38
【问题描述】:

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

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

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

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 年。

结果应该是这样的:

     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

任何帮助将不胜感激!

【问题讨论】:

  • 您能详细说明第(2)点吗?抵达年份如何计算?带有示例的步骤将有所帮助
  • 感谢您的反馈,我添加了一个示例以进行澄清!
  • 请注意您的示例数据有 traveldistance = [120,70,37,40,20,... 但您打印的数据框有 2004: 50 而不是最后一个 20,请在发布/编辑问题之前检查代码
  • @RichieV 谢谢你的回答!我编辑了一次示例,并且一定错过了该值。现在要尝试您的解决方案,感谢您花时间和精力回复!
  • 别担心,我喜欢挑战作为训练,最终我们都会有所收获

标签: python pandas conditional-statements


【解决方案1】:

我不知道有任何针对这种特定情况的 pandas 内置方法。但这里有一个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

【讨论】:

    猜你喜欢
    • 2018-07-30
    • 1970-01-01
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 2013-06-20
    • 2019-04-27
    • 2017-05-16
    相关资源
    最近更新 更多