【问题标题】:Select a row if two consecutive columns contain a negative value如果两个连续的列包含负值,则选择一行
【发布时间】:2023-01-09 15:40:51
【问题描述】:

从下面给出的通货膨胀率表中,我想获得连续两年负通货膨胀率的国家。

            2017 2018   2019    2020    2021    2022
Country                     
Turkey      NaN  47.0   -7.0    -19.0   38.0    260.0
Argentina   NaN  33.0   56.0    -22.0   15.0    8.0
Suriname    NaN  -68.0  -37.0   695.0   56.0    13.0
Zimbabwe    NaN  106.0  2306.0  118.0   -83.0   -21.0
Lebanon     NaN  2.0    -36.0   2826.0  82.0    39.0
Sudan       NaN  96.0   -19.0   220.0   19.0    34.0
Venezuela   NaN  1482.0 -70.0   -88.0   15.0    -89.0

我在 SO 中看到了一些使用列表理解或循环的解决方案。我想知道没有他们是否可以完成这项任务。

我试图将数据帧转换为 1 和 0,其中 1.0 表示负通货膨胀。

           2017 2018 2019 2020 2021 2022
Country                     
Turkey      NaN 0.0 1.0 1.0 0.0 0.0
Argentina   NaN 0.0 0.0 1.0 0.0 0.0
Suriname    NaN 1.0 1.0 0.0 0.0 0.0
Zimbabwe    NaN 0.0 0.0 0.0 1.0 1.0
Lebanon     NaN 0.0 1.0 0.0 0.0 0.0
Sudan       NaN 0.0 1.0 0.0 0.0 0.0
Venezuela   NaN 0.0 1.0 1.0 0.0 1.0

但是,我被困在这一点上。我尝试使用 np.prod 函数,但如果至少有一列为 0.0 数据,则返回 0。

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: pandas dataframe


    【解决方案1】:

    您可以先为负值设置一个整数掩码(1 表示负数)。然后计算轴 1 上的滚动最小值,最小值是 1,所有值都是。这可以推广到任意数量的连续列。

    N = 2
    m1 = df.lt(0).astype(int)
    m2 = m.rolling(N, axis=1).min().eq(1).any(axis=1)
    
    df[m2]
    

    输出:

               2017    2018    2019   2020  2021   2022
    Country                                            
    Turkey      NaN    47.0    -7.0  -19.0  38.0  260.0
    Suriname    NaN   -68.0   -37.0  695.0  56.0   13.0
    Zimbabwe    NaN   106.0  2306.0  118.0 -83.0  -21.0
    Venezuela   NaN  1482.0   -70.0  -88.0  15.0  -89.0
    

    注意。人们需要使用整数,因为滚动目前仅限于数字类型

    N=2 的单个掩码替代方案

    m = df.lt(0)
    df[(m&m.shift(axis=1)).any(axis=1)]
    

    【讨论】:

      【解决方案2】:

      尝试这个:

      match = (df.lt(0) & df.shift(axis=1).lt(0)).any(axis=1)
      df[match]
      

      怎么运行的:

      • df.lt(0):当年通胀小于0
      • df.shift(axis=1).lt(0):上年通胀小于0
      • .any(axis=1):该国发生的任何此类事件。

      【讨论】:

        【解决方案3】:

        鉴于您的数据框,这对我有用:

        • 将国家/地区设置为索引,这样我的 df 值中只有数字
        • 使用 df.shift(axis=1) 定义新列以检查列中的“两个连续负数”。

        所以它看起来像:

        df.set_index('Country',inplace=True)
        df['TwoNegatives'] = ((df.values < 0) & ((df.shift(axis=1)).values <0)).any(axis=1)
        

        【讨论】:

        • 这与前一段时间在其他两个解决方案中提供的大致相同;)
        【解决方案4】:

        试试rolling

        out = df[df.le(0).T.rolling(window=2).sum().ge(2).any()]
        Out[15]: 
                   2017    2018    2019   2020  2021   2022
        Country                                            
        Turkey      NaN    47.0    -7.0  -19.0  38.0  260.0
        Suriname    NaN   -68.0   -37.0  695.0  56.0   13.0
        Zimbabwe    NaN   106.0  2306.0  118.0 -83.0  -21.0
        Venezuela   NaN  1482.0   -70.0  -88.0  15.0  -89.0
        

        【讨论】:

          【解决方案5】:
          df1.applymap(lambda x:x if pd.isna(x) else float(x<0)).pipe(print)
          
          out
          
                     2017  2018  2019  2020  2021  2022
          Country                                      
          Turkey      NaN   0.0   1.0   1.0   0.0   0.0
          Argentina   NaN   0.0   0.0   1.0   0.0   0.0
          Suriname    NaN   1.0   1.0   0.0   0.0   0.0
          Zimbabwe    NaN   0.0   0.0   0.0   1.0   1.0
          Lebanon     NaN   0.0   1.0   0.0   0.0   0.0
          Sudan       NaN   0.0   1.0   0.0   0.0   0.0
          Venezuela   NaN   0.0   1.0   1.0   0.0   1.0
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-02-02
            • 1970-01-01
            • 2021-11-30
            • 2019-10-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多