【问题标题】:how I can count signs columns?我如何计算标志列?
【发布时间】:2022-10-25 18:58:21
【问题描述】:

如何计算每行中重复的正元素或负元素的数量?

假设我有以下数据:

ski      2020    2021      2022     2023       2024      2025
book      1.2     5.6       8.4      -2         -5         6
jar       4.2      -5        -8      2          4           6
kook       -4      -5.2      -2.3    -5.6        -7        8

输出是每行的一个列表,用于计算相似符号的数量。例如,在第一行中,我们有 3 个正元素,然后是 2 个负元素,然后是一个正元素。所以输出是[3,-2,1]。对于其他 2 行,输出如下:

 jar   [1,-2,3]
 kook   [-5,1]

【问题讨论】:

  • 有些值可能是 0 吗?

标签: pandas


【解决方案1】:

使用 DataFrame.clip 和自定义 lambda function 计算连续值:

#if necessary
df = df.set_index('ski')
print (df)
      2020  2021  2022  2023  2024  2025
ski                                     
book   1.2   5.6   8.4  -2.0    -5     6
jar    4.2  -5.0  -8.0   2.0     4     6
kook  -4.0  -5.2  -2.3  -5.6    -7     8


from  itertools import groupby

f = lambda x: [ int(sum(key for _ in group)) for key, group in groupby( x )]
s = df.clip(upper=1, lower=-1).apply(f, 1)
print (s)
ski
book    [3, -2, 1]
jar     [1, -2, 3]
kook       [-5, 1]
dtype: object

【讨论】:

    【解决方案2】:

    让我们试试:

    s = np.sign(df.set_index('ski').stack())
    s.groupby([pd.Grouper(level=0), s.diff().ne(0).cumsum()]).sum().groupby(level=0).agg(list)
    

    ski
    book    [3.0, -2.0, 1.0]
    jar     [1.0, -2.0, 3.0]
    kook         [-5.0, 1.0]
    dtype: object
    

    【讨论】:

      【解决方案3】:

      利用:

      import pandas as pd
      import numpy as np
      data = '''ski      2020    2021      2022     2023       2024      2025
      book      1.2     5.6       8.4      -2         -5         6
      jar       4.2      -5        -8      2          4           6
      kook       -4      -5.2      -2.3    -5.6        -7        8'''
      data = np.array([x.split() for x in data.split('
      ')])
      
      import seaborn as sns
      
      df = pd.DataFrame(data[1:,1:], columns = data[0,1:], index = data[1:,0])
      
      
      output = []
      import math
      for i, row in df.iterrows():
          out = []
          c=0
          prev = math.copysign(1,float(row[0]))
          temp = row.append(pd.Series(-math.copysign(1,float(row[-1]))))
          for cell in temp:
              
              currrent_sign = math.copysign(1,float(cell))
              #print(prev, currrent_sign, c)
              if currrent_sign==prev:
                  c+=currrent_sign
              else:
                  prev = currrent_sign
                  out.append(c)
                  c=currrent_sign
          output.append(out)
      

      输出:

      [[3.0, -2.0, 1.0], [1.0, -2.0, 3.0], [-5.0, 1.0]]
      

      【讨论】:

        【解决方案4】:

        我假设滑雪是索引列。如果不是,则将其设置为索引,删除当前索引。

        从定义一个函数开始,应用于每一行:

        def myCounts(row):
            sgn = row.ge(0)
            return sgn.groupby(sgn.ne(sgn.shift()).cumsum()).apply(
                lambda grp: grp.count() * (1 if grp.iloc[0] else -1)).tolist()
        

        然后应用它:

        result = df.apply(myCounts, axis=1)
        

        对于您的源数据,我得到:

        ski
        book    [3, -2, 1]
        jar     [1, -2, 3]
        kook       [-5, 1]
        dtype: object
        

        我的解决方案比另一个解决方案要短得多。

        【讨论】:

          【解决方案5】:
          df1.set_index('ski').stack().reset_index()
              .assign(col1=lambda dd:np.sign(dd.iloc[:,2]))
              .assign(col2=lambda dd2:(dd2.col1.diff()!=0).cumsum())
              .groupby(['ski','col2'],as_index=False).col1.sum()
              .groupby(['ski'],as_index=False).col1.agg(list).pipe(print)
          
            ski              col1
          0  book  [3.0, -2.0, 1.0]
          1   jar  [1.0, -2.0, 3.0]
          2  kook       [-5.0, 1.0]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-12-12
            • 1970-01-01
            • 2015-06-17
            • 2020-08-31
            • 1970-01-01
            • 2011-02-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多