【问题标题】:Duplicating each column of a csv and changing values of every column cell based on a condition in python复制csv的每一列并根据python中的条件更改每个列单元格的值
【发布时间】:2020-11-02 01:19:12
【问题描述】:

我是所有东西的新用户,尤其是 python 和 pandas。我有一个包含 1000 多列和大约 250 行的 .csv 文件。行的值为 0 和 1 或空单元格。下面给出了一个csv文件的例子:

  ID       col1   col2    col3  col4 .  . ............... col1000                          
  1          1     0              1                         1
  2          0              1     1                 
  3                1              0                         0                                                                   
  .
  .
  .
  .
 250         0     1              0                         0
         

我想做两件事:

首先,我想复制所有 1000 列(ID 列除外),其单元格值和列名与原始列相同,然后按以下顺序将每个复制的列放在原始列旁边:

col1      col1     col2     col2    col3    col3     col4     col4 ...... col1000      col1000

其次,我想根据以下条件替换单元格中的值:

如果原始单元格中有 1,则复制列中的值应保持为 1,如果原始列单元格中有 0,则复制列中的值应更改为 -1。如果原始单元格为空,则原始单元格和复制单元格的值应填充为 0 值。

输出的 csv 文件将是:

  ID     col1    col1   col2   col2   col3    col3   col4   col4 . ........... col1000   col1000                         
  1        1       1      0     -1      0       0      1      1                    1        1
  2        0      -1      0      0      1       1      1      1                    0        0
  3        0       0      1      1      0       0      0     -1                    0       -1                                                          
  .
  .
  .
  .
 250       0      -1     1       1      0       0      0     -1                    0       -1

我无法解决它,如果有人可以帮助我,我真的很感激;谢谢...

【问题讨论】:

    标签: python excel pandas numpy csv


    【解决方案1】:

    您可以执行以下步骤,诀窍是使用列索引来获取正确的列序列:

    # create copied data and concat into original
    df2 = pd.concat([df, df.replace(0,-1).fillna(0).drop('ID', axis=1)], 1)
    
    # since column names are same, we need to use index
    cols = [x for x in df2.columns if x != 'ID']
    cols = dict(enumerate(cols))
    
    # get correct index for column names
    cols_index = [x[0] for x in sorted(cols.items(), key=lambda x: x[1])]
    
    # fix column names
    idcol = df2[['ID']]
    df2 = df2.drop('ID', 1).iloc[:,cols_index]
    
    # add the ID column
    df2 = pd.concat([idcol, df2], 1).fillna(0)
    
    print(df2)
    
       ID  col1  col1  col2  col2  col3  col3
    0   1   1.0   1.0   1.0   1.0   1.0   1.0
    1   2   0.0   0.0   0.0   0.0   0.0   0.0
    2   3   NaN  -1.0   NaN  -1.0   NaN  -1.0
    3   4   NaN  -1.0   NaN  -1.0   NaN  -1.0
    4   5   1.0   1.0   1.0   1.0   1.0   1.0
    

    样本数据

    df = pd.DataFrame({'ID': list(range(1,6)),
                       'col1':[1,0,np.NaN,np.NaN,1],
                       'col2':[1,0,np.NaN,np.NaN,1],
                       'col3':[1,0,np.NaN,np.NaN,1]})
    

    【讨论】:

    • 嗨,感谢它的工作,尤其是所需列的顺序,但在原始列(未复制)中,nan 值不会被零替换,但我可以这样做,而且 -1 替换是不适用于 nan 值,但仅当原始列单元格中的值为 0 时,复制的单元格应该有一个 -1 我也可以更正。非常感谢...
    • @codeDB 感谢您的反馈,我已经更新了答案。如果有帮助,请将其标记为已接受。
    • 嗨,对不起,我刚刚意识到我的数据有错误。价值置换条件错误。如果原始单元格 (col1) 的值为 1,则复制的相同单元格 (col1) 的值应为 -1,原始单元格的值保持为 1。类似地,如果原始单元格的值为 0,则原始单元格的这个 0 应该更改为-1,相同复制单元格的值应为1。对于空单元格,原始和复制的规则相同,应填充0。我用 df.replace({a:b,b:c}) 函数尝试了它,但它不起作用。你能帮我解决这个问题吗?
    【解决方案2】:

    你可以试试这个看看是否有效。

    import pandas as pd
    import numpy as np
    

    起始数据

    df = pd.DataFrame({'col1':[1,0,np.NaN,np.NaN,1],'col2':[1,0,np.NaN,np.NaN,1],'col3':[1,0,np.NaN,np.NaN,1]})
    

    首先复制原始df。

    df_copy = df.copy()
    

    然后根据上述条件替换副本中的值。

    columns =  df_copy.columns
    df_copy[columns] = np.where(df_copy[columns]==0,-1,df_copy[columns])
    

    然后用 0 填充空白值。

    df_copy = df_copy.fillna(0)
    

    为排序添加列数。

    df.loc['total'] = np.arange(len(df.columns))
    df_copy.loc['total'] = np.arange(len(df_copy.columns))
    

    然后将两个df连接在一起

    new_df = pd.concat([df,df_copy],axis=1)
    

    使用列计数行对列进行排序,然后从新的 df 中删除该行

    new_df = new_df.sort_values(by='total',axis=1)
    new_df = new_df.loc[~new_df.index.isin(['total'])]
    

    【讨论】:

    • 不,它给出了两个错误:A:“AttributeError:'numpy.ndarray'对象没有属性'fillna”如果我将fillna放在np.where行之前,那么第二个错误是:B: TypeError: 无法连接类型为 '' 的对象;只有 Series 和 DataFrame obj 是有效的。
    • 我删除了错误,现在它可以工作了,但是输出文件不是我需要的。
    • 您是否将 pandas 导入为 pd 并将 numpy 导入为 np?
    • 我查看了代码并意识到我跳过了一步......上面修改了
    • 感谢您的帮助,我运行了代码,但很抱歉它没有提供所需的输出,尽管它根据条件替换了值,但仅在复制的数据帧中,即文件的后半部分,也在那里是空单元格,我提到的顺序不存在,因为顺序很重要,我的意思是复制的单元格应该在原始单元格之后,如 col1 col1 col2 col2 而连接确实给出了这个顺序
    【解决方案3】:

    您可以使用此方法(与使用 pandas 内置函数替换的其他答案类似的方法):

    df2 = df.copy().replace(0,-1).fillna(0).drop(['ID'],1)
    df = pd.concat([df.fillna(0),df2],1)
    

    输出和样本输入(对于不同的输入样本,但列的比较是显而易见的):

    输入:

         ID  col1  col2  col3  col4  col1000
    0     1     1     0     1   1.0      NaN
    1     2     0     1     1   NaN      NaN
    2     3     1     0     0   NaN      NaN
    250   250     0     1     0   0.0      NaN
    

    输出:

        ID  col1  col2  col3  col4 ... col1000  col1  col2  col3  col4 ... col1000
    0    1     1     0     1   1.0      0.0     1    -1     1   1.0      0.0
    1    2     0     1     1   0.0      0.0    -1     1     1   0.0      0.0
    2    3     1     0     0   0.0      0.0     1    -1    -1   0.0      0.0
    ...
    250  250     0     1     0   0.0      0.0    -1     1    -1  -1.0      0.0
    

    【讨论】:

    • 您好,感谢您的回答,但有没有办法维持我需要的顺序?我必须进一步处理数据,为此我需要我在相关输出文件中提到的相同顺序。每个复制的列必须位于原始列之后,例如 col1 col1 col2 col2 col3 col3 and son on,否则它不能达到目的。
    • 10000多列250多行,无法手动比较
    • @codeDB 您是否关心它们是否具有相同的列名,或者它们的名称中是否可以有例如后缀col1_oldcol1_new
    • 嗨 Ehsan 没问题,但列的顺序和位置不应该改变
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 2021-05-21
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多