Avertissement de l'utilisateur Python Pandas: tri car l'axe de non-concaténation n'est pas aligné

93

Je fais de la pratique du code et j'applique la fusion de trames de données tout en faisant cela, en obtenant un avertissement de l'utilisateur

/usr/lib64/python2.7/site-packages/pandas/core/frame.py:6201: FutureWarning: tri car l'axe de non-concaténation n'est pas aligné. Une future version de pandas changera pour ne pas trier par défaut. Pour accepter le comportement futur, transmettez 'sort = True'. Pour conserver le comportement actuel et faire taire l'avertissement, transmettez sort = False

Sur ces lignes de code: Pouvez-vous s'il vous plaît aider à obtenir la solution de cet avertissement.

placement_video = [self.read_sql_vdx_summary, self.read_sql_video_km]
placement_video_summary = reduce(lambda left, right: pd.merge(left, right, on='PLACEMENT', sort=False), placement_video)


placement_by_video = placement_video_summary.loc[:, ["PLACEMENT", "PLACEMENT_NAME", "COST_TYPE", "PRODUCT",
                                                     "VIDEONAME", "VIEW0", "VIEW25", "VIEW50", "VIEW75",
                                                     "VIEW100",
                                                     "ENG0", "ENG25", "ENG50", "ENG75", "ENG100", "DPE0",
                                                     "DPE25",
                                                     "DPE50", "DPE75", "DPE100"]]

# print (placement_by_video)

placement_by_video["Placement# Name"] = placement_by_video[["PLACEMENT",
                                                            "PLACEMENT_NAME"]].apply(lambda x: ".".join(x),
                                                                                     axis=1)

placement_by_video_new = placement_by_video.loc[:,
                         ["PLACEMENT", "Placement# Name", "COST_TYPE", "PRODUCT", "VIDEONAME",
                          "VIEW0", "VIEW25", "VIEW50", "VIEW75", "VIEW100",
                          "ENG0", "ENG25", "ENG50", "ENG75", "ENG100", "DPE0", "DPE25",
                          "DPE50", "DPE75", "DPE100"]]

placement_by_km_video = [placement_by_video_new, self.read_sql_km_for_video]
placement_by_km_video_summary = reduce(lambda left, right: pd.merge(left, right, on=['PLACEMENT', 'PRODUCT'], sort=False),
                                       placement_by_km_video)

#print (list(placement_by_km_video_summary))
#print(placement_by_km_video_summary)
#exit()
# print(placement_by_video_new)
"""Conditions for 25%view"""
mask17 = placement_by_km_video_summary["PRODUCT"].isin(['Display', 'Mobile'])
mask18 = placement_by_km_video_summary["COST_TYPE"].isin(["CPE", "CPM", "CPCV"])
mask19 = placement_by_km_video_summary["PRODUCT"].isin(["InStream"])
mask20 = placement_by_km_video_summary["COST_TYPE"].isin(["CPE", "CPM", "CPE+", "CPCV"])
mask_video_video_completions = placement_by_km_video_summary["COST_TYPE"].isin(["CPCV"])
mask21 = placement_by_km_video_summary["COST_TYPE"].isin(["CPE+"])
mask22 = placement_by_km_video_summary["COST_TYPE"].isin(["CPE", "CPM"])
mask23 = placement_by_km_video_summary["PRODUCT"].isin(['Display', 'Mobile', 'InStream'])
mask24 = placement_by_km_video_summary["COST_TYPE"].isin(["CPE", "CPM", "CPE+"])

choice25video_eng = placement_by_km_video_summary["ENG25"]
choice25video_vwr = placement_by_km_video_summary["VIEW25"]
choice25video_deep = placement_by_km_video_summary["DPE25"]

placement_by_km_video_summary["25_pc_video"] = np.select([mask17 & mask18, mask19 & mask20, mask17 & mask21],
                                                  [choice25video_eng, choice25video_vwr, choice25video_deep])


"""Conditions for 50%view"""
choice50video_eng = placement_by_km_video_summary["ENG50"]
choice50video_vwr = placement_by_km_video_summary["VIEW50"]
choice50video_deep = placement_by_km_video_summary["DPE50"]

placement_by_km_video_summary["50_pc_video"] = np.select([mask17 & mask18, mask19 & mask20, mask17 & mask21],
                                                  [choice50video_eng,
                                                   choice50video_vwr, choice50video_deep])

"""Conditions for 75%view"""

choice75video_eng = placement_by_km_video_summary["ENG75"]
choice75video_vwr = placement_by_km_video_summary["VIEW75"]
choice75video_deep = placement_by_km_video_summary["DPE75"]

placement_by_km_video_summary["75_pc_video"] = np.select([mask17 & mask18, mask19 & mask20, mask17 & mask21],
                                                  [choice75video_eng,
                                                   choice75video_vwr,
                                                   choice75video_deep])

"""Conditions for 100%view"""

choice100video_eng = placement_by_km_video_summary["ENG100"]
choice100video_vwr = placement_by_km_video_summary["VIEW100"]
choice100video_deep = placement_by_km_video_summary["DPE100"]
choicecompletions = placement_by_km_video_summary['COMPLETIONS']

placement_by_km_video_summary["100_pc_video"] = np.select([mask17 & mask22, mask19 & mask24, mask17 & mask21, mask23 & mask_video_video_completions],
                                                          [choice100video_eng, choice100video_vwr, choice100video_deep, choicecompletions])



"""conditions for 0%view"""

choice0video_eng = placement_by_km_video_summary["ENG0"]
choice0video_vwr = placement_by_km_video_summary["VIEW0"]
choice0video_deep = placement_by_km_video_summary["DPE0"]

placement_by_km_video_summary["Views"] = np.select([mask17 & mask18, mask19 & mask20, mask17 & mask21],
                                                   [choice0video_eng,
                                                    choice0video_vwr,
                                                    choice0video_deep])


#print (placement_by_km_video_summary)
#exit()

#final Table

placement_by_video_summary = placement_by_km_video_summary.loc[:,
                             ["PLACEMENT", "Placement# Name", "PRODUCT", "VIDEONAME", "COST_TYPE",
                              "Views", "25_pc_video", "50_pc_video", "75_pc_video","100_pc_video",
                              "ENGAGEMENTS","IMPRESSIONS", "DPEENGAMENTS"]]

#placement_by_km_video = [placement_by_video_summary, self.read_sql_km_for_video]
#placement_by_km_video_summary = reduce(lambda left, right: pd.merge(left, right, on=['PLACEMENT', 'PRODUCT']),
                                       #placement_by_km_video)


#print(placement_by_video_summary)
#exit()
# dup_col =["IMPRESSIONS","ENGAGEMENTS","DPEENGAMENTS"]

# placement_by_video_summary.loc[placement_by_video_summary.duplicated(dup_col),dup_col] = np.nan

# print ("Dhar",placement_by_video_summary)

'''adding views based on conditions'''
#filter maximum value from videos

placement_by_video_summary_new = placement_by_km_video_summary.loc[
    placement_by_km_video_summary.reset_index().groupby(['PLACEMENT', 'PRODUCT'])['Views'].idxmax()]
#print (placement_by_video_summary_new)
#exit()
# print (placement_by_video_summary_new)
# mask22 = (placement_by_video_summary_new.PRODUCT.str.upper ()=='DISPLAY') & (placement_by_video_summary_new.COST_TYPE=='CPE')

placement_by_video_summary_new.loc[mask17 & mask18, 'Views'] = placement_by_video_summary_new['ENGAGEMENTS']
placement_by_video_summary_new.loc[mask19 & mask20, 'Views'] = placement_by_video_summary_new['IMPRESSIONS']
placement_by_video_summary_new.loc[mask17 & mask21, 'Views'] = placement_by_video_summary_new['DPEENGAMENTS']

#print (placement_by_video_summary_new)
#exit()
placement_by_video_summary = placement_by_video_summary.drop(placement_by_video_summary_new.index).append(
    placement_by_video_summary_new).sort_index()

placement_by_video_summary["Video Completion Rate"] = placement_by_video_summary["100_pc_video"] / \
                                                      placement_by_video_summary["Views"]

placement_by_video_final = placement_by_video_summary.loc[:,
                           ["Placement# Name", "PRODUCT", "VIDEONAME", "Views",
                            "25_pc_video", "50_pc_video", "75_pc_video", "100_pc_video",
                            "Video Completion Rate"]]
MishD
la source

Réponses:

136

tl; dr:

concatet appendtrier actuellement l'index de non-concaténation (par exemple les colonnes si vous ajoutez des lignes) si les colonnes ne correspondent pas. Dans les pandas 0.23, cela a commencé à générer un avertissement; passez le paramètre sort=Truepour le désactiver. À l'avenir, la valeur par défaut changera pour ne pas trier, il est donc préférable de spécifier soit sort=Trueou Falsemaintenant, ou mieux encore de vous assurer que vos indices de non-concaténation correspondent.


L'avertissement est nouveau dans pandas 0.23.0 :

Dans une future version de pandas pandas.concat()et DataFrame.append()ne triera plus l'axe de non-concaténation lorsqu'il n'est pas déjà aligné. Le comportement actuel est le même que le précédent (tri), mais maintenant un avertissement est émis lorsque le tri n'est pas spécifié et que l'axe de non-concaténation n'est pas aligné, lien .

Plus d'informations sur le très vieux problème lié à github, commentaire de smcinerney :

Lors de la concatation de DataFrames, les noms de colonnes sont triés de manière alphanumérique s'il existe des différences entre eux. S'ils sont identiques dans les DataFrames, ils ne sont pas triés.

Ce type est non documenté et indésirable. Le comportement par défaut doit certainement être sans tri.

Après un certain temps, le paramètre a sortété implémenté dans pandas.concatet DataFrame.append:

sort : booléen, par défaut Aucun

Trier l'axe de non-concaténation s'il n'est pas déjà aligné lorsque la jointure est «externe». Le tri par défaut actuel est obsolète et passera au non-tri dans une future version de pandas.

Passez explicitement sort = True pour faire taire l'avertissement et le tri. Passez explicitement sort = False pour faire taire l'avertissement et ne pas trier.

Cela n'a aucun effet lorsque join = 'inner', qui préserve déjà l'ordre de l'axe de non-concaténation.

Donc, si les deux DataFrames ont les mêmes colonnes dans le même ordre, il n'y a pas d'avertissement ni de tri:

df1 = pd.DataFrame({"a": [1, 2], "b": [0, 8]}, columns=['a', 'b'])
df2 = pd.DataFrame({"a": [4, 5], "b": [7, 3]}, columns=['a', 'b'])

print (pd.concat([df1, df2]))
   a  b
0  1  0
1  2  8
0  4  7
1  5  3

df1 = pd.DataFrame({"a": [1, 2], "b": [0, 8]}, columns=['b', 'a'])
df2 = pd.DataFrame({"a": [4, 5], "b": [7, 3]}, columns=['b', 'a'])

print (pd.concat([df1, df2]))
   b  a
0  0  1
1  8  2
0  7  4
1  3  5

Mais si les DataFrames ont des colonnes différentes, ou les mêmes colonnes dans un ordre différent, pandas renvoie un avertissement si aucun paramètre sortn'est explicitement défini ( sort=Nonec'est la valeur par défaut):

df1 = pd.DataFrame({"a": [1, 2], "b": [0, 8]}, columns=['b', 'a'])
df2 = pd.DataFrame({"a": [4, 5], "b": [7, 3]}, columns=['a', 'b'])

print (pd.concat([df1, df2]))

FutureWarning: tri car l'axe de non-concaténation n'est pas aligné.

   a  b
0  1  0
1  2  8
0  4  7
1  5  3

print (pd.concat([df1, df2], sort=True))
   a  b
0  1  0
1  2  8
0  4  7
1  5  3

print (pd.concat([df1, df2], sort=False))
   b  a
0  0  1
1  8  2
0  7  4
1  3  5

Si les DataFrames ont des colonnes différentes, mais que les premières colonnes sont alignées, elles seront correctement affectées les unes aux autres (colonnes aet bde df1avec aet bde df2dans l'exemple ci-dessous) car elles existent dans les deux. Pour les autres colonnes qui existent dans un mais pas dans les deux DataFrames, des valeurs manquantes sont créées.

Enfin, si vous passez sort=True, les colonnes sont triées par ordre alphanumérique. Si sort=Falseet le deuxième DafaFrame a des colonnes qui ne sont pas dans la première, elles sont ajoutées à la fin sans tri:

df1 = pd.DataFrame({"a": [1, 2], "b": [0, 8], 'e':[5, 0]}, 
                    columns=['b', 'a','e'])
df2 = pd.DataFrame({"a": [4, 5], "b": [7, 3], 'c':[2, 8], 'd':[7, 0]}, 
                    columns=['c','b','a','d'])

print (pd.concat([df1, df2]))

FutureWarning: tri car l'axe de non-concaténation n'est pas aligné.

   a  b    c    d    e
0  1  0  NaN  NaN  5.0
1  2  8  NaN  NaN  0.0
0  4  7  2.0  7.0  NaN
1  5  3  8.0  0.0  NaN

print (pd.concat([df1, df2], sort=True))
   a  b    c    d    e
0  1  0  NaN  NaN  5.0
1  2  8  NaN  NaN  0.0
0  4  7  2.0  7.0  NaN
1  5  3  8.0  0.0  NaN

print (pd.concat([df1, df2], sort=False))

   b  a    e    c    d
0  0  1  5.0  NaN  NaN
1  8  2  0.0  NaN  NaN
0  7  4  NaN  2.0  7.0
1  3  5  NaN  8.0  0.0

Dans votre code:

placement_by_video_summary = placement_by_video_summary.drop(placement_by_video_summary_new.index)
                                                       .append(placement_by_video_summary_new, sort=True)
                                                       .sort_index()
jezrael
la source
21
Je ne comprends pas très bien ceci: In a future version of pandas pandas.concat() and DataFrame.append() will no longer sort the non-concatenation axis when it is not already aligned. qu'est-ce qu'un non-concatenation axiset à quoi ressemblera le résultat? la colonne a et la colonne b ne correspondent-elles pas? ou juste l'ordre des colonnes est différent?
une offre ne peut pas refuser le
9
Ce que cela is not alignedsignifie n'est pas clair - pourriez-vous commenter cela?
Mr_and_Mrs_D
1
Je crois alignedque cela signifie que les niveaux dans l'axe sont les mêmes: s'il y a une différence de quelque nature que ce soit, ils ne le sont plus alignedet vont déclencher ce comportement (par exemple si les niveaux des axes sont ['c','b','a']et ['a'])
Robert Muil
3
@RobertMuil Je pense que l'utilisation du terme levelici est potentiellement déroutante, car elle levela une signification spécifique pour les dataframes pandas quand il y a un MultiIndex. D'après ce que je comprends, aligneddans ce contexte se réfère à l'ordre de l'index de ligne / colonne. Ainsi, si l'ordre d'index de l'axe de non-concaténation est différent pour vos deux images, vous pouvez spécifier s'il faut conserver l'ordre dans la première image passée et trier la deuxième image pour qu'elle corresponde, ou trier l'index des DEUX images avant la concaténation. C'est un domaine déroutant pour moi aussi, donc les corrections sont les bienvenues!
ac24
Les colonnes sont alignées quand tuple(df1.columns) == tuple(df2.columns). L'axe de non-concaténation est l'axe (lignes ou colonnes) parallèle aux coutures le long desquelles les DataFrames sont assemblées.
BallpointBen
107

La réponse de jezrael est bonne, mais n'a pas répondu à une question que j'avais: Est-ce que le mauvais flag "sort" va gâcher mes données de quelque façon que ce soit? La réponse est apparemment "non", vous allez bien de toute façon.

from pandas import DataFrame, concat

a = DataFrame([{'a':1,      'c':2,'d':3      }])
b = DataFrame([{'a':4,'b':5,      'd':6,'e':7}])

>>> concat([a,b],sort=False)
   a    c  d    b    e
0  1  2.0  3  NaN  NaN
0  4  NaN  6  5.0  7.0

>>> concat([a,b],sort=True)
   a    b    c  d    e
0  1  NaN  2.0  3  NaN
0  4  5.0  NaN  6  7.0
RLC
la source
qu'est-ce qui est exactement trié ou non trié?
Ben
2
@Ben, l'avertissement apparaît lorsque l'ordre des colonnes est différent entre les dataframes. Comme vous pouvez le voir si sort = True, les colonnes après concatentation sont triées par ordre alphabétique
MP23
Dans cet exemple, ce n'est pas le cas, mais si vous concaténez plusieurs Series ou DataFrames avec un DatetimeIndex, les lignes ne sont plus dans l'ordre chronologique. Techniquement, les données ne sont pas faussées, mais votre résultat peut être plus difficile à lire.
hugovdberg