【问题标题】:How to manipulate repeated data values in mulitple columns with python如何使用python操作多列中的相关数据值
【发布时间】:2021-02-27 22:47:50
【问题描述】:

我有大约 50 列,并且列的行以相似的值重复。例如:

Idx    Series    Col1   Col2  Col3  Col4  Col5 .....   Col50 
 0      A                 1                   
 1      A                 1
 2      A                 1
 3      A                 1
 4      B        3             2                          3
 5      B        3             2                          3
 6      B        3             2                          3
 7      B        3             2                          3
 8      C                4                1
 9      C                4                1
10      C                4                1
11      C                4                1

我想根据其位置从重复值中保留一个值,并将其他值更改为'0'

因此,如果值为“4”,则保留第 4 个位置的值,并将前三个更改为“0”。同样,如果值为 '1',则保留第一个,其余更改为 '0'。

输出列将是:

Idx    Series    Col1   Col2  Col3  Col4  Col5 .....   Col50 
 0      A                 1                   
 1      A                 0
 2      A                 0
 3      A                 0
 4      B        0             0                          0
 5      B        0             2                          0
 6      B        3             0                          3
 7      B        0             0                          0
 8      C                0                1
 9      C                0                0
10      C                0                0
11      C                4                0

任何帮助将不胜感激。

谢谢你..

【问题讨论】:

    标签: python pandas dataframe csv indexing


    【解决方案1】:

    由于您的 DataFrame 不包含 NaN 值,我假设:

    • 列 Col1 到 Col50 属于 object 类型,
    • 它们包含 字符串 数据,可以是空字符串或字符串 包含一个数字字符。

    要获得预期的结果,请定义以下 2 个函数:

    1. 要应用于要转换的每一列的函数:

      def cnv(col):
          return col.groupby((col != col.shift()).cumsum()).apply(cnv2)
      
    2. 要应用于当前列中每个组的函数:

      def cnv2(grp):
          if grp.str.isnumeric().all():
              ind = grp.index[0]
              val = int(grp.iloc[0])
              return grp.where(grp.index == val + ind - 1, '0')
          else:
              return grp
      

    然后对要转换的列应用cnv函数,保存结果 返回相同的列:

    df.loc[:, 'Col1':'Col50'] = df.loc[:, 'Col1':'Col50'].apply(cnv)
    

    结果是:

        Idx Series Col1 Col2 Col3 Col5 Col50
    0     0      A         1                
    1     1      A         0                
    2     2      A         0                
    3     3      A         0                
    4     4      B    0         0          0
    5     5      B    0         2          0
    6     6      B    3         0          3
    7     7      B    0         0          0
    8     8      C         0         1      
    9     9      C         0         0      
    10   10      C         0         0      
    11   11      C         4         0      
    

    【讨论】:

    • 非常感谢您的帮助。实际上,我收到“if grp.str.isnumeric().all():”错误,错误是:AttributeError: Can only use .str accessor with string values!,这显然意味着这些值不是 str 或对象类型没有值的列实际上是空列..
    • 我假设所有 Col... 列都是 object 类型并包含 strings。显然,您的 DataFrame 中的某些内容以其他方式排列,但您没有指定如何。按照我的预期生成您的 DataFrame(所有字符串,可能为空),然后尝试我的代码。
    • @Valdi_Bo:非常感谢您的帮助。更改数据类型后,代码现在可以工作了。感谢您的帮助..
    【解决方案2】:

    让我们做

    df2 = df.replace(r'^\s*$', np.nan, regex=True)
    new_df = (df2.assign(**df2.filter(regex='Col')
                              .where(lambda x: x.eq(df.groupby('Series')
                                                    .cumcount()
                                                    .add(1), 
                                                 axis=0) | x.isna() , 
                                  0)
                      )
                 .fillna('') # I recommend remove this line
             )
    print(new_df)
    

    输出

        Idx Series Col1 Col2 Col3
    0     0      A         1     
    1     1      A         0     
    2     2      A         0     
    3     3      A         0     
    4     4      B    0         0
    5     5      B    0         2
    6     6      B    3         0
    7     7      B    0         0
    8     8      C         0     
    9     9      C         0     
    10   10      C         0     
    11   11      C         4     
    

    【讨论】:

    • @ansev:感谢您的回答。我在 ".where(lambda x: x.eq(df2.groupby('Series)" 行中的系列列出现错误。我认为系列列可能被设置为索引,这可能是错误的原因。我会添加另一个索引并尝试查看它是否有效。
    • Groupby.cumcount 让原始索引因为为每个 SeriesGroup 值分配一个 int?什么是错误代码?你用的是什么熊猫版本?提前致谢
    • 非常感谢@ansev。我做了必要的修改和它现在的工作。只是一个小问题。如果我想用另一个值替换所有值(0,1,2,3)让我们说用1,我怎么能根据你的代码而不是单独通过将范围传递给pandas .replace函数来做到这一点?
    • 可以在.replace方法后面加上.where(lambda x: x.notna(), 1)
    • 在 .replace 方法之后,它将替换所有值,我指的是在应用 groupby 方法之前重复的值。我想在重复值更改为 -1 后替换它们,并且 (0,1,2,3) 中只有一个值留在其索引位置。现在我想更改它,这意味着我将在 .fllna() 函数之前添加您建议的代码,对吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    相关资源
    最近更新 更多