Pandas Python: conservez la colonne sélectionnée en tant que DataFrame au lieu de Series

92

Lors de la sélection d' une seule colonne d'une trame de données pandas ( par exemple df.iloc[:, 0], df['A']ou df.A, etc), le vecteur résultant est automatiquement converti en une série au lieu d'une trame de données à colonne unique. Cependant, j'écris des fonctions qui prennent un DataFrame comme argument d'entrée. Par conséquent, je préfère traiter avec DataFrame à colonne unique au lieu de Series afin que la fonction puisse supposer que df.columns est accessible. À l'heure actuelle, je dois convertir explicitement la série en un DataFrame en utilisant quelque chose comme pd.DataFrame(df.iloc[:, 0]). Cela ne semble pas être la méthode la plus propre. Existe-t-il un moyen plus élégant d'indexer directement à partir d'un DataFrame afin que le résultat soit un DataFrame à une seule colonne au lieu de Series?


la source
6
df.iloc [:, [0]] ou df [['A']]; df.A seulement rendra une série cependant
Jeff

Réponses:

99

Comme @Jeff le mentionne, il existe plusieurs façons de le faire, mais je recommande d'utiliser loc / iloc pour être plus explicite (et signaler les erreurs tôt si vous essayez quelque chose d'ambigu):

In [10]: df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 'B'])

In [11]: df
Out[11]:
   A  B
0  1  2
1  3  4

In [12]: df[['A']]

In [13]: df[[0]]

In [14]: df.loc[:, ['A']]

In [15]: df.iloc[:, [0]]

Out[12-15]:  # they all return the same thing:
   A
0  1
1  3

Les deux derniers choix suppriment toute ambiguïté dans le cas des noms de colonne entiers (précisément pourquoi loc / iloc a été créé). Par exemple:

In [16]: df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 0])

In [17]: df
Out[17]:
   A  0
0  1  2
1  3  4

In [18]: df[[0]]  # ambiguous
Out[18]:
   A
0  1
1  3
Andy Hayden
la source
2
Désolé de vous déranger, mais juste une question très rapide à ce sujet. Je vois comment le supplément []rend le résultat un DataFrameau lieu d'un Series, mais où dans la documentation pandas ce type de syntaxe d'indexation est-il discuté? J'essaye juste d'obtenir le nom "officiel" de cette technique d'indexation pour que je la comprenne vraiment. Merci!
sparc_spread
3
@sparc_spread pandas.pydata.org/pandas-docs/stable/indexing.html#basics "Vous pouvez transmettre une liste de colonnes à [] pour sélectionner les colonnes dans cet ordre." Je ne sais pas si cela a un nom!
Andy Hayden
Ouais, on dirait qu'il n'en a pas - mais je continuerai de l'utiliser à partir de maintenant. Incroyable combien de choses sont enterrées à la fois dans l'API et dans la documentation. Merci!
sparc_spread
Cette distinction a été utile pour moi, car parfois je veux une seule colonne DataFrame afin que je puisse utiliser les méthodes DataFrame sur les données qui n'étaient pas disponibles sur Series. (ISTR la méthode de tracé s'est comportée différemment). Ce fut une révélation pour moi quand j'ai réalisé que je pouvais utiliser une liste à un seul élément!
RufusVS
4

Comme Andy Hayden le recommande, l'utilisation de .iloc / .loc pour indexer les cadres de données (à une seule colonne) est la voie à suivre; un autre point à noter est comment exprimer les positions d'index. Utilisez des étiquettes / positions d'index répertoriées tout en spécifiant les valeurs d'argument à indexer en tant que Dataframe; ne pas le faire renverra un 'pandas.core.series.Series'

Contribution:

    A_1 = train_data.loc[:,'Fraudster']
    print('A_1 is of type', type(A_1))
    A_2 = train_data.loc[:, ['Fraudster']]
    print('A_2 is of type', type(A_2))
    A_3 = train_data.iloc[:,12]
    print('A_3 is of type', type(A_3))
    A_4 = train_data.iloc[:,[12]]
    print('A_4 is of type', type(A_4))

Production:

    A_1 is of type <class 'pandas.core.series.Series'>
    A_2 is of type <class 'pandas.core.frame.DataFrame'>
    A_3 is of type <class 'pandas.core.series.Series'>
    A_4 is of type <class 'pandas.core.frame.DataFrame'>
Sumanth Lazarus
la source
1

Vous pouvez utiliser df.iloc[:, 0:1], dans ce cas le vecteur résultant sera une DataFramesérie et non une série.

Comme vous pouvez le voir:

entrez la description de l'image ici

p47hf1nd3r
la source
1

Ces trois approches ont été évoquées:

pd.DataFrame(df.loc[:, 'A'])  # Approach of the original post
df.loc[:,[['A']]              # Approach 2 (note: use iloc for positional indexing)
df[['A']]                     # Approach 3

pd.Series.to_frame () est une autre approche.

Comme il s'agit d'une méthode, elle peut être utilisée dans des situations où les deuxième et troisième approches ci-dessus ne s'appliquent pas. En particulier, il est utile lorsque vous appliquez une méthode à une colonne de votre dataframe et que vous souhaitez convertir la sortie en dataframe au lieu d'une série. Par exemple, dans un Jupyter Notebook, une série n'aura pas une jolie sortie, mais une dataframe en aura.

# Basic use case: 
df['A'].to_frame()

# Use case 2 (this will give you pretty output in a Jupyter Notebook): 
df['A'].describe().to_frame()

# Use case 3: 
df['A'].str.strip().to_frame()

# Use case 4: 
def some_function(num): 
    ...

df['A'].apply(some_function).to_frame()
Null_Vallue_
la source