【问题标题】:How to vectorize code with nested if and loops in Python?如何在 Python 中使用嵌套的 if 和循环对代码进行矢量化?
【发布时间】:2019-12-31 17:34:36
【问题描述】:

我有一个如下所示的数据框

df = pd.DataFrame({
    'subject_id' :[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
    'day':[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
    'PEEP' :[7,5,10,10,11,11,14,14,17,17,21,21,23,23,25,25,22,20,26,26,5,7,8,8,9,9,13,13,15,15,12,12,15,15,19,19,19,22,22,15]
})
df['fake_flag'] = ''

在此操作中,我正在执行如下代码所示的操作。此代码工作正常并产生预期的输出,但我不能将这种方法用于真实数据集,因为它有超过百万条记录。

t1 = df['PEEP']
for i in t1.index:
   if i >=2:
      print("current value is  ", t1[i])
      print("preceding 1st (n-1) ", t1[i-1])
      print("preceding 2nd (n-2) ", t1[i-2])
         if (t1[i-1] == t1[i-2] or t1[i-2] >= t1[i-1]):
            r1_output = t1[i-2] # we get the max of these two values (t1[i-2]), it doesn't matter when it's constant(t1[i-2] or t1[i-1]) will have the same value anyway
            print("rule 1 output is ", r1_output)
            if t1[i] >= r1_output + 3:
                print("found a value for rule 2", t1[i])
                print("check for next value is same as current value", t1[i+1])
                if (t1[i]==t1[i+1]):
                    print("fake flag is being set")
                    df['fake_flag'][i] = 'fake_vac'

但是,我无法将其应用于真实数据,因为它有超过一百万条记录。我正在学习 Python,你能帮我理解如何在 Python 中对我的代码进行矢量化吗?

你可以参考这个帖子related post来理解逻辑。因为我的逻辑是正确的,所以我创建了这篇文章主要是为了寻求帮助来矢量化和固定我的代码

我希望我的输出如下所示

subject_id = 1

subject_id = 2

有没有什么高效优雅的方法来固定我对一百万条记录数据集的代码操作

【问题讨论】:

  • t1 是否与df 相同?
  • 更新了帖子
  • 如果您提供输出 df 文本描述您正在尝试做的事情的视图会更好
  • 更新了帖子@AkashKumar
  • 5th 列中给出'fake VAC' 值的逻辑是什么?我觉得numpy.where()可以用在这里。

标签: python python-3.x pandas vectorization pandas-groupby


【解决方案1】:

不知道这背后的故事是什么,但你当然可以独立地将三个if矢量化并将它们组合在一起,

con1 = t1.shift(2).ge(t1.shift(1))
con2 = t1.ge(t1.shift(2).add(3))
con3 = t1.eq(t1.shift(-1))

df['fake_flag']=np.where(con1 & con2 & con3,'fake VAC','')

编辑(Groupby SubjectID)

con = lambda x: (x.shift(2).ge(x.shift(1))) & (x.ge(x.shift(2).add(3))) & (x.eq(x.shift(-1)))

df['fake_flag'] = df.groupby('subject_id')['PEEP'].transform(con).map({True:'fake VAC',False:''})

【讨论】:

  • 哇,太棒了。没想到会这么简单。非常感谢您的宝贵时间。
  • 我认为您还需要应用 groupby 以防止 subject1 和 subject 2 混合。
  • @Mark Wang - 你介意用 groupby 更新你的答案以对其他人有用吗?是的,我们需要基于每个subject_id
  • 感谢您的帮助。非常感谢。
  • 略有不同。看看你能不能拿起不同的东西..con = lambda x:(x['PEEP'].shift(2).ge(x['PEEP'].shift(1))) & (x['PEEP'].ge(x['PEEP'].shift(2).add(3))) & (x['PEEP2'].eq(x['PEEP2'].shift(-1))),df['fake_flag'] = df.groupby('subject_id').apply(con).map({True:'fake VAC',False:''}).reset_index(level=0,drop=True)
【解决方案2】:

这行得通吗?

df.groupby('subject_id')\
  .rolling(3)['PEEP'].apply(lambda x: (x[-1] - x[:2].max()) >= 3, raw=True).fillna(0).astype(bool)

输出:

subject_id    
1           0     False
            1     False
            2      True
            3     False
            4     False
            5     False
            6      True
            7     False
            8      True
            9     False
            10     True
            11    False
            12    False
            13    False
            14    False
            15    False
            16    False
            17    False
            18     True
            19    False
2           20    False
            21    False
            22    False
            23    False
            24    False
            25    False
            26     True
            27    False
            28    False
            29    False
            30    False
            31    False
            32     True
            33    False
            34     True
            35    False
            36    False
            37     True
            38    False
            39    False
Name: PEEP, dtype: bool

详情:

  • 使用groupby 使用“subject_id”分解数据
  • 应用rolling,n=3 或窗口大小为 3。
  • 使用 -1 索引和 subtact 查看该窗口中的最后一个值 使用索引的该窗口中前两个值的最大值 切片。

【讨论】:

  • 哇,你真棒。你介意为像我这样的初学者提供一些细节吗?我想它正在工作。我可以在所有正确的地方看到True
  • 如果你能分解,我可以逐个执行来实际理解,然后申请不同的数据(真实数据)
  • 您按主题 id 分组,然后使用滚动三个值的窗口...取该窗口中的最后一个值,然后从窗口中前两个值的最大值中减去 if。检查是否大于 3。
  • 但您还必须检查下一个值 (n+1)。您使用n 并检查n-1n-2,然后确保nn+1 相同
  • 如果你看到我的输出截图,你会有一个想法,我希望这会有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 2018-11-13
  • 2015-09-04
相关资源
最近更新 更多