创建具有多个匹配项的新列

时间:2019-03-08 11:36:23

标签: python pandas

样本DF:

我有一个df,其中包含ZoneNew_ZoneCountryNew_RegionCurrency之类的列

Currency列的值类似EURAUDBLRRUB

Zone列的值类似EUAfricaNAZ

New_Zone的值类似于EUEuropeEUROPEAfricaNAZAFRICA

Country的值类似于AustraliaBrazilRussiaUkraineUSA

New_Region的值类似于AustraliaBrazilUSA

因此,列ZoneNew_Zone包含几乎相似的值,列New_RegionCountry包含几乎相似的值

询问:

我想在满足以下条件的情况下创建一个名为Currency_Match的新列:

  1. 如果Zone是EU OR (逻辑)New_Zone是EU,欧洲或EUROPE (逻辑)货币是EUR,则是其他否
  2. 如果国家/地区为澳大利亚 OR (逻辑)新地区为澳大利亚 AND (逻辑)货币为AUD,则为其他否
  3. 如果国家/地区为巴西 OR (逻辑)新地区为巴西 AND (逻辑)货币为BLR,则为其他否
  4. 如果国家/地区为韩国 OR (逻辑)新地区为韩国 AND (逻辑)货币为KRW,则其他为否

  5. 如果区域是非洲 OR (逻辑)New_Zone是非洲或非洲,则 AND (逻辑)货币是NGN,则是,否则是< / p>

6如果Zone是NAZ OR (逻辑)New_Zone是NAZ,则 AND (逻辑)货币是USD,则是其他

7如果国家/地区是俄罗斯,乌克兰 OR (逻辑)新地区是俄罗斯 AND (逻辑)货币是RUB,则是否

我总共有上述7种情况

代码:

        df['Currency_Match']=df.apply(lambda row: "Yes" if (((row['Zone'] == "EU")|(row['New_Zone'] =='Europe')|(row['New_Zone'] =='EU')|(row['New_Zone'] =='EUROPE')) 
& (row["Contract - Original Currency Code"] == "EUR"))
     else 'No',axis=1)

问题:

上面的代码运行良好,但是当我编写类似这样的其他条件时,它会一次又一次地更新列。

他们有其他方法可以做到吗,而且也比这麻烦吗

1 个答案:

答案 0 :(得分:2)

为可读代码的单独行创建每个条件,按|&进行按链ORAND的链接,以形成最终掩码并传递到numpy.where

m1 = (df['Zone'] == "EU")|(df['New_Zone'].isin(['Europe','EUROPE','EU'])
m2 = (df["Contract - Original Currency Code"] == "EUR")

m3 = (df['Region'] == "Australia")|(df['New_Region'] =='Australia')
m4 = (df["Contract - Original Currency Code"] == "AUD")

m5 = (df['Region'] == "Brazil")|(df['New_Region'] =='Brazil')
m6 = (df["Contract - Original Currency Code"] == "BLR")

mask = (m1 & m2) | (m3 & m4) | (m5 & m6)

df['Currency_Match'] = np.where(mask, "Yes", 'No')

编辑:对于动态解决方案,请按货币创建带有区域和区域列表的字典,然后传递到dict comprehension中的logical_or.reduce

#zone dict
d1 = {'EUR':['Europe','EUROPE','EU'],'NGN':['Africa','AFRICA'],'USD':['NAZ']}

#region dict
d2 = {'AUD':['Australia'], 'BLR':['Brazil'],'KRW':['Korea'],'RUB':['Russia','Ukraine']}

m1 = [(df['Zone'].isin(v) | df['New_Zone'].isin(v)) & 
      (df["Contract - Original Currency Code"] == k) 
       for k, v in d1.items()]
print (m1)

m2 = [(df['Region'].isin(v) | df['New_Region'].isin(v)) & 
      (df["Contract - Original Currency Code"] == k) 
       for k, v in d2.items()]
print (m2)

mask = np.logical_or.reduce(m1) | np.logical_or.reduce(m2)

df['Currency_Match'] = np.where(mask, "Yes", 'No')