Je travaille avec certaines données pour lesquelles les données du code postal du client ne sont pas valides. En conséquence, je ne suis pas en mesure de mapper le CountryISOCode à son code postal, ce qui entraîne un NaN. Cependant, j'ai remarqué que pour tous les CountryISOCodes avec NaN, le CurrencyCode peut me fournir suffisamment pour résoudre le problème pour le moment.
J'ai consulté divers articles de Stackoverflow mais je ne trouve pas la solution à mon problème. J'ai essayé ...
IF countryISOCode IS NULL
AND currency = âGBPâ
THEN CountryISOCode = âGBRâ
ELSE
IF countryISOCode IS NULL
AND currency = âEUR
THEN CountryISOCode = âIREâ
ELSE countryISOCode
END
et quelques autres méthodes mais en vain ...
Ci-dessous, j'ai fourni une réplication des données que j'ai Je travaille avec
import pandas as pd
import numpy as np
data = [
['Steve', 'Invalid Postcode', 'GBP', np.nan ],
['Robyn', 'Invalid Postcode', 'EUR', np.nan],
['James', 'Valid Postcode', 'GBP', 'GBR'],
['Halo', 'Invalid Postcode', 'EUR', np.nan],
['Jesus', 'Valid Postcode', 'GBP', 'GBR']
]
df = pd.DataFrame(columns=["Name", "PostCode", "CurrencyCode", "CountryISOCode"], data=data)
Essentiellement, si je travaillais avec SQL, mon code serait le suivant.
def func(row):
if row['CountryISOCode'] == np.nan & row['Currency'] == 'EUR':
return 'IRE'
elif row['CountryISOCode'] == np.nan & row['Currency'] == 'GBP':
return 'GBR'
else:
return row['CountryISOCode']
df['CountryISOCode'] = df.apply(func, axis=1)
Toutes les idées ?
5 Réponses :
Vous pouvez utiliser np .select pour cela, qui vous permet de choisir dans une liste en fonction du résultat d'une liste de conditions:
m1 = df.CountryISOCode.isna()
m2 = df.CurrencyCode.eq('GBP')
m3 = df.CurrencyCode.eq('EUR')
df.loc[:,'CountryISOCode'] = np.select([m1&m2, m1&m3], ['GBP','IRE'],
default=df.CountryISOCode)
Name PostCode CurrencyCode CountryISOCode
0 Steve Invalid Postcode GBP GBP
1 Robyn Invalid Postcode EUR IRE
2 James Valid Postcode GBP GBR
3 Halo Invalid Postcode EUR IRE
4 Jesus Valid Postcode GBP GBR
Ce type de fonctionnement fonctionne mais il remplit une valeur GBP avec IRE qui ne fonctionnerait pas. Index 2
Merci d'avoir répondu à ma question! Votre solution a fonctionné.
utilisez np.select () pour plusieurs conditions et plusieurs choix:
df['CountryISOCode']=np.select([(df.CurrencyCode=='GBP')&(df.CountryISOCode.isna()),\
(df.CurrencyCode=='EUR')&df.CountryISOCode.isna()],['GBR','IRE'],\
default=df.CountryISOCode)
Name PostCode CurrencyCode CountryISOCode
0 Steve Invalid Postcode GBP GBR
1 Robyn Invalid Postcode EUR IRE
2 James Valid Postcode GBP GBR
3 Halo Invalid Postcode EUR IRE
4 Jesus Valid Postcode GBP GBR
Merci d'avoir répondu à ma question! Votre solution a fonctionné.
Vous pouvez utiliser fillna avec un dictionnaire spécifiant les mappages lorsque le code de devise est utile:
cmap = {'GBP': 'GBR', 'EUR': 'IRE'}
df['CountryISOCode'] = df['CountryISOCode'].fillna(df['CurrencyCode'].map(cmap))
print(df)
Name PostCode CurrencyCode CountryISOCode
0 Steve Invalid Postcode GBP GBR
1 Robyn Invalid Postcode EUR IRE
2 James Valid Postcode GBP GBR
3 Halo Invalid Postcode EUR IRE
4 Jesus Valid Postcode GBP GBR
Cette solution a résolu mon problème de la manière la plus simple ... Un changement mineur est qu'il devrait être cmap = {'GBP': 'GBR', 'EUR': 'IRE'}
Alors que l'autre réponse utilisant np.select fonctionne, mon favori personnel utilise mask:
df['CountryISOCode'] = df['CountryISOCode'] \
.mask(df['CountryISOCode'].isna() & df['Currency'].eq('GBP'), 'GBR') \
.mask(df['CountryISOCode'].isna() & df['Currency'].eq('EUR'), 'IRE')
Merci d'avoir répondu à ma question!.
J'ajoute cette réponse car elle ajoute de la valeur à la question d'origine. La raison pour laquelle les instructions de comparaison ne fonctionnaient pas est que np.nan == np.nan ne fonctionnera pas. Vous pouvez vérifier l'identité de l'élément NaN mais pas l'égalité. Voir dans operator, float ("NaN") et np.nan pour en savoir plus détail. Cela dit, voici comment vous pouvez transformer le code d'origine pour qu'il fonctionne comme prévu.
import pandas as pd
import numpy as np
raw_data = [
['Steve', 'Invalid Postcode', 'GBP', np.nan ],
['Robyn', 'Invalid Postcode', 'EUR', np.nan],
['James', 'Valid Postcode', 'GBP', 'GBR'],
['Halo', 'Invalid Postcode', 'EUR', np.nan],
['Jesus', 'Valid Postcode', 'GBP', 'GBR']
]
df = pd.DataFrame(columns=["Name", "PostCode", "Currency", "CountryISOCode"], data=raw_data)
def func(row):
if row['CountryISOCode'] is np.nan and row['Currency'] == 'EUR':
return 'IRE'
elif row['CountryISOCode'] is np.nan and row['Currency'] == 'GBP':
return 'GBR'
else:
return row['CountryISOCode']
df['CountryISOCode'] = df.apply(func, axis=1)
print(df)
Cependant, les autres réponses sont également excellentes.
Avez-vous essayé de remplacer
&paret? Il y a une différence entre les deux et je pense que vous voulez utiliseretici. Vous pouvez en savoir plus sur la différence ici [ stackoverflow.com/questions/22646463/...Le code fonctionne avec
etmais ne semble pas résoudre le problème. Les données restent les mêmes.