Aviso do usuário do Python Pandas: classificação porque o eixo de não concatenação não está alinhado

91

Estou fazendo alguma prática de código e aplicando mesclagem de quadros de dados enquanto faço isso, recebendo um aviso do usuário

/usr/lib64/python2.7/site-packages/pandas/core/frame.py:6201: FutureWarning: classificação porque o eixo de não concatenação não está alinhado. Uma versão futura do pandas mudará para não classificar por padrão. Para aceitar o comportamento futuro, passe 'sort = True'. Para manter o comportamento atual e silenciar o aviso, passe sort = False

Nestas linhas de código: Você pode ajudar a obter a solução para este aviso.

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
fonte

Respostas:

135

tl; dr:

concate appendatualmente classifica o índice de não concatenação (por exemplo, colunas se você estiver adicionando linhas) se as colunas não corresponderem. No pandas 0.23, isso começou a gerar um aviso; passe o parâmetro sort=Truepara silenciá-lo. No futuro, o padrão mudará para não classificar, então é melhor especificar um sort=Trueou Falseagora, ou melhor ainda, garantir que seus índices de não concatenação correspondam.


O aviso é novo no pandas 0.23.0 :

Em uma versão futura do pandas pandas.concat()e DataFrame.append()não classificará mais o eixo de não concatenação quando ainda não estiver alinhado. O comportamento atual é igual ao anterior (classificação), mas agora um aviso é emitido quando a classificação não é especificada e o eixo de não concatenação não está alinhado, link .

Mais informações sobre o problema do github muito antigo vinculado , comentário de smcinerney :

Ao concatenar DataFrames, os nomes das colunas são classificados alfanumericamente se houver alguma diferença entre eles. Se eles forem idênticos nos DataFrames, eles não serão classificados.

Esse tipo é não documentado e indesejado. Certamente, o comportamento padrão deve ser sem classificação.

Depois de algum tempo, o parâmetro sortfoi implementado em pandas.concate DataFrame.append:

sort : boolean, default None

Classifique o eixo de não concatenação se ainda não estiver alinhado quando a junção for 'externa'. O padrão atual de classificação está obsoleto e mudará para não classificação em uma versão futura do pandas.

Passe explicitamente sort = True para silenciar o aviso e classificar. Passe explicitamente sort = False para silenciar o aviso e não classificar.

Isso não tem efeito quando join = 'inner', que já preserva a ordem do eixo de não concatenação.

Portanto, se os dois DataFrames tiverem as mesmas colunas na mesma ordem, não haverá nenhum aviso e nenhuma classificação:

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

Mas se os DataFrames tiverem colunas diferentes ou as mesmas colunas em uma ordem diferente, o pandas retornará um aviso se nenhum parâmetro sortfor definido explicitamente ( sort=Noneé o valor padrão):

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: Classificando porque o eixo de não concatenação não está alinhado.

   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

Se os DataFrames tiverem colunas diferentes, mas as primeiras colunas estiverem alinhadas - elas serão atribuídas corretamente uma à outra (colunas ae bde df1com ae bde df2no exemplo abaixo) porque existem em ambos. Para outras colunas que existem em um, mas não em ambos os DataFrames, os valores ausentes são criados.

Por último, se você passar sort=True, as colunas serão classificadas alfanumericamente. Se sort=Falsee o segundo DafaFrame tiver colunas que não estão no primeiro, elas serão anexadas ao final sem classificação:

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: Classificando porque o eixo de não concatenação não está alinhado.

   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

Em seu código:

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
fonte
21
Não entendo muito bem: o 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. que é um non-concatenation axise como será o resultado? a coluna a e a coluna b serão incompatíveis? ou apenas a ordem das colunas é diferente?
uma oferta não pode recusar
9
Não está claro o que is not alignedsignifica - você poderia comentar sobre isso?
Mr_and_Mrs_D
1
Eu acredito alignedque significa que os níveis no eixo são os mesmos: se houver uma diferença de qualquer tipo, eles não são mais alignede irão desencadear esse comportamento (por exemplo, se os níveis do eixo forem ['c','b','a']e ['a'])
Robert Muil
3
@RobertMuil Acho que usar o termo levelaqui é potencialmente confuso, pois leveltem um significado específico para dataframes do pandas quando há um MultiIndex. Pelo que entendi, alignedneste contexto se refere à ordenação do índice de linha / coluna. Portanto, se a ordem do índice do eixo de não concatenação for diferente para seus dois quadros, você pode especificar se deseja manter a ordem no primeiro quadro passado e classificar o segundo quadro para corresponder ou classificar o índice de AMBOS os quadros antes da concatenação. Esta é uma área confusa para mim, então correções bem-vindas!
ac24 de
As colunas são alinhadas quando tuple(df1.columns) == tuple(df2.columns). O eixo de não concatenação é o eixo (linhas ou colunas) paralelo às costuras ao longo das quais os DataFrames estão sendo costurados.
BallpointBen
107

A resposta de jezrael é boa, mas não respondeu a uma pergunta que eu tinha: obter o sinalizador "sort" errado bagunçará meus dados de alguma forma? A resposta é aparentemente "não", você está bem de qualquer maneira.

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
fonte
o que exatamente é hier classificado ou não classificado?
Ben
2
@Ben, o aviso aparece quando a ordem das colunas é diferente entre os dataframes. Como você pode ver se sort = True, as colunas após a concatentação são classificadas em ordem alfabética
MP23
Neste exemplo, não, mas se você concatenar várias Series ou DataFrames com um DatetimeIndex, as linhas não estarão mais em ordem cronológica. Tecnicamente, os dados não estão bagunçados, mas seu resultado pode ser mais difícil de ler.
hugovdberg