【问题标题】:How to create a new column with values from comparing two other columns?如何使用比较其他两列的值创建一个新列?
【发布时间】:2019-07-04 04:39:52
【问题描述】:

我正在开展一个项目,该项目将对拥有计算机帐户的员工进行审计。我想打印一个包含两个新列的数据框。这与 Comparing Columns in Dataframes 问题不同,因为我正在使用字符串。我还需要做一些模糊逻辑,但那是进一步的。

我收到的数据在 Excel 表格中。它来自两个我无法控制的来源,因此我将它们格式化为 [First Name, Last Name] 并将它们打印到控制台以确保我正在使用的数据是正确的。我将 .xls 转换为 .csv 文件,格式化信息,并能够在具有两列的单个数据框中输出两个名称列表,但无法将我想要的值放在最后两列中。我使用了查询(返回真/假,而不是名称)、差异和正则表达式。我认为我只是错误地使用了这些工具。

    import pandas as pd

    nd = {'col1': ["Abraham Hansen","Demetrius McMahon","Hilary 
          Emerson","Amelia H. Hayden","Abraham Oliver"],
          'col2': ["Abraham Hansen","Abe Oliver","Hillary Emerson","DJ 
          McMahon","Amelia H. Hayden"]}
    info = pd.DataFrame(data=nd)

    for row in info:
    if info.col1.value not in info.col2:
        info["Need Account"] = info.col1.value

    if info.col2.value not in info.col1:
        info["Delete Account"] = info.col2.value

    print(info)

我想要一个包含 2 列的新数据框:需要帐户和删除帐户,并根据数据框中的其他列填写适当的值。在这种情况下,我收到“系列”没有属性“值”的错误。 这是我的预期输出示例:

    df_out: 
    Need Account       Delete Account
    Demetrius McMahon  Abe Oliver
    Abraham Oliver     Hillary Emerson
    Hilary Emerson     DJ McMahon

从这个列表中,我可以查看出现了谁的昵称,然后从那里减少列表。

【问题讨论】:

  • 样本数据的预期输出是什么?
  • 我不认为for row in info 正在做你认为的那样。尝试将循环的内容更改为for row in infor: print(row) 以检查输出。
  • 预期的输出是增加了两列,需要帐户和删除帐户。我将用预期的输出更新问题

标签: python pandas


【解决方案1】:

您想使用isinnp.where 有条件地分配新值:

info['Need Account'] = np.where(~info['col1'].isin(info['col2']), info['col1'], np.NaN)
info['Delete Account'] = np.where(~info['col2'].isin(info['col1']), info['col2'], np.NaN)

                col1              col2       Need Account   Delete Account
0     Abraham Hansen    Abraham Hansen                NaN              NaN
1  Demetrius McMahon        Abe Oliver  Demetrius McMahon       Abe Oliver
2     Hilary Emerson   Hillary Emerson     Hilary Emerson  Hillary Emerson
3   Amelia H. Hayden        DJ McMahon                NaN       DJ McMahon
4     Abraham Oliver  Amelia H. Hayden     Abraham Oliver              NaN

或者如果你想要一个新的数据框,就像你在问题中所说的那样:

need = np.where(~info['col1'].isin(info['col2']), info['col1'], np.NaN)
delete = np.where(~info['col2'].isin(info['col1']), info['col2'], np.NaN)

newdf = pd.DataFrame({'Need Account':need,
                      'Delete Account':delete})

        Need Account   Delete Account
0                NaN              NaN
1  Demetrius McMahon       Abe Oliver
2     Hilary Emerson  Hillary Emerson
3                NaN       DJ McMahon
4     Abraham Oliver              NaN

【讨论】:

  • 我尝试在项目的早期版本中使用 np.where,但无法让它像这样工作。感谢您花时间帮助我。
  • 当然没问题,那是否回答了您的问题?
  • 它确实回答了我的问题。我将进一步研究 NumPy 如何实现“在哪里”,以便更好地了解您的答案中发生了什么。总是有更多的东西要学。
【解决方案2】:

我没有看到您的预期输出,而是在阅读您在代码中尝试的内容。让我知道这是否是您要找的?

nd = {'col1': ["Abraham Hansen","Demetrius McMahon","Hilary Emerson","Amelia H. Hayden","Abraham Oliver"],
      'col2': ["Abraham Hansen","Abe Oliver","Hillary Emerson","DJ McMahon","Amelia H. Hayden"], 
      'Need Account':"", 
      'Delete Account':""
     }
info = pd.DataFrame(data=nd)

print(info)

               col1              col2 Need Account Delete Account
0     Abraham Hansen    Abraham Hansen                            
1  Demetrius McMahon        Abe Oliver                            
2     Hilary Emerson   Hillary Emerson                            
3   Amelia H. Hayden        DJ McMahon                            
4     Abraham Oliver  Amelia H. Hayden    

不要使用循环,使用向量...

info.loc[info['col1'] != info['col2'], 'Need Account'] = info['col1']
info.loc[info['col2'] != info['col1'], 'Delete Account'] = info['col2']

print(info)

               col1              col2       Need Account    Delete Account
0     Abraham Hansen    Abraham Hansen                                     
1  Demetrius McMahon        Abe Oliver  Demetrius McMahon        Abe Oliver
2     Hilary Emerson   Hillary Emerson     Hilary Emerson   Hillary Emerson
3   Amelia H. Hayden        DJ McMahon   Amelia H. Hayden        DJ McMahon
4     Abraham Oliver  Amelia H. Hayden     Abraham Oliver  Amelia H. Hayden

【讨论】:

  • 非常接近!我更改了问题,因为我认为仅将另外两列放入其中可能太难了。谢谢!我将研究一种遍历每个列表以比较它们的方法(在示例中,Amelia 将被排除在需要/删除帐户列之外)。再次感谢您!
  • 如果一定要循环,可以使用iterrows,但是pandas的实力确实是向量解法,我相信你的问题可以通过这种方式解决。
  • 那么我将专注于向量。我通过在工作中寻找项目来自学 Python。我真的很感谢你的帮助。如何将您的答案标记为回答了我的问题的答案?
  • 经过足够的时间后,它将显示在左侧。我在 pandas 中最大的收获是停止思考传统循环,开始思考向量。你会发现这开启了一种全新的思维方式。去年我用 pandas 做了一个大程序,但陷入了循环。太棒了。一旦光线继续理解矢量,我的整个世界就改变了。保持矢量角度,它会来的!
【解决方案3】:

IIUC,您的输入数据框中似乎没有太多“结构”需要维护,因此您可以使用集合直接比较组中的成员资格。

nd = {'col1': ["Abraham Hansen","Demetrius McMahon","Hilary Emerson","Amelia H. Hayden","Abraham Oliver"],
      'col2': ["Abraham Hansen","Abe Oliver","Hillary Emerson","DJ McMahon","Amelia H. Hayden"]}
df = pd.DataFrame(data=nd)

col1 = set(df['col1'])
col2 = set(df['col2'])

need = col1 - col2
delete = col2 - col1

print('need = ', need)
print('delete =  ', delete)

产量

need =  {'Hilary Emerson', 'Demetrius McMahon', 'Abraham Oliver'}
delete =   {'Hillary Emerson', 'DJ McMahon', 'Abe Oliver'}

然后你可以放入一个新的数据框:

data = {'need':list(need), 'delete':list(delete)}
new_df = pd.DataFrame.from_dict(data, orient='index').transpose()

(编辑以考虑needdelete 长度不等的可能性。)

【讨论】:

  • 你是对的,我不需要维护结构。更多的是关于将信息从当前的 600 多个名称的 excel 文件减少到不匹配的信息。感谢您花时间帮助我。
猜你喜欢
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多