Comment obtenir une valeur à partir d'une cellule d'une trame de données?


347

J'ai construit une condition qui extrait exactement une ligne de mon bloc de données:

d2 = df[(df['l_ext']==l_ext) & (df['item']==item) & (df['wn']==wn) & (df['wd']==1)]

Maintenant, je voudrais prendre une valeur dans une colonne particulière:

val = d2['col_name']

Mais en conséquence, j'obtiens un bloc de données qui contient une ligne et une colonne ( c'est-à-dire une cellule). Ce n'est pas ce dont j'ai besoin. J'ai besoin d'une valeur (un nombre flottant). Comment puis-je le faire chez les pandas?


1
Si vous avez essayé certaines de ces réponses mais que SettingWithCopyWarningvous vous êtes retrouvé avec un , vous pouvez consulter ce post pour une explication de l'avertissement et des solutions / solutions possibles.
cs95

Réponses:


430

Si vous avez un DataFrame avec une seule ligne, accédez à la première (uniquement) ligne en tant que série à l'aide iloc, puis à la valeur en utilisant le nom de la colonne:

In [3]: sub_df
Out[3]:
          A         B
2 -0.133653 -0.030854

In [4]: sub_df.iloc[0]
Out[4]:
A   -0.133653
B   -0.030854
Name: 2, dtype: float64

In [5]: sub_df.iloc[0]['A']
Out[5]: -0.13365288513107493

1
@Sophologist regardant cela, je n'en ai aucune idée. La question est un peu étrangement formulée, mais elle se lit comme si la première moitié était sans importance pour cette dernière. ( atest une réponse vraiment sympa, bien que je trouve cela étrange, c'est comme ix:))
Andy Hayden

9
@Sophologist Je conviens que c'est ridicule que cela soit nécessaire. Cela ne fonctionne pas non plus lorsque vous essayez de passer les conditions en ligne; my_df.loc[my_df['Col1'] == foo]['Col2']renvoie toujours un objet de type<class 'pandas.core.series.Series'>
user5359531

16
Notez que cette solution renvoie une série, pas une valeur!
Atte Juvonen

1
@AtteJuvonen Cela dépend si vous avez des doublons dans votre index / colonnes (note à / iat déclenche une exception avec les colonnes en double, va déposer un problème).
Andy Hayden

1
bizarre. Je continue à lire loc est pour les noms et iloc est pour les entiers mais ici, c'est iloc pour l'entier et le nom
mLstudent33

205

Ce sont un accès rapide pour les scalaires

In [15]: df = pandas.DataFrame(numpy.random.randn(5,3),columns=list('ABC'))

In [16]: df
Out[16]: 
          A         B         C
0 -0.074172 -0.090626  0.038272
1 -0.128545  0.762088 -0.714816
2  0.201498 -0.734963  0.558397
3  1.563307 -1.186415  0.848246
4  0.205171  0.962514  0.037709

In [17]: df.iat[0,0]
Out[17]: -0.074171888537611502

In [18]: df.at[0,'A']
Out[18]: -0.074171888537611502

9
J'aime beaucoup cette réponse. Mais alors que vous pouvez le faire, .iloc[-1]['A']vous ne pouvez pas le faire at[-1,'A']pour obtenir l'entrée de la dernière ligne
hartmut

3
cela devrait être la réponse, car nous ne copions pas en mémoire une ligne inutile pour obtenir un seul élément à l'intérieur.
bormat

3
@hartmut Vous pouvez toujours faireat[df.index[-1],'A']
cs95

105

Vous pouvez transformer votre trame de données 1x1 en un tableau numpy, puis accéder à la première et unique valeur de ce tableau:

val = d2['col_name'].values[0]

10
Veuillez améliorer la qualité de votre réponse avec un peu plus d'explications.
Franck Gamess

Modifiez votre réponse initiale avec ceci avant de créer un commentaire. Merci
Franck Gamess

2
Je préfère cette méthode et l'utilise fréquemment. Utilisé .get_values()[0]également.
aaronpenne

3
Je pense que c'est la meilleure réponse car elle ne renvoie pas de pandas.series, et c'est la plus simple.
Sean McCarthy

Quel avantage cela a-t-il sur les méthodes fournies par les pandas?
AMC

28

La plupart des réponses utilisent ilocce qui est bon pour la sélection par position.

Si vous avez besoin d'une sélection par étiquette, ce loc serait plus pratique.

Pour obtenir une valeur de manière explicite (équivalent à df.get_value déprécié ('a', 'A'))

# this is also equivalent to df1.at['a','A']
In [55]: df1.loc['a', 'A'] 
Out[55]: 0.13200317033032932

18

J'avais besoin de la valeur d'une cellule, sélectionnée par les noms de colonne et d'index. Cette solution a fonctionné pour moi:

original_conversion_frequency.loc[1,:].values[0]


16

Cela ressemble à des changements après les pandas 10.1 / 13.1

J'ai mis à jour la version 10.1 vers la version 13.1, avant qu'iloc ne soit pas disponible.

Maintenant avec 13.1, iloc[0]['label']obtient un tableau à valeur unique plutôt qu'un scalaire.

Comme ça:

lastprice=stock.iloc[-1]['Close']

Production:

date
2014-02-26 118.2
name:Close, dtype: float64

Je pense que cela ne devrait être le cas que pour les séries avec des entrées en double ... en fait, je ne vois pas cela, pourriez-vous donner un petit exemple pour le démontrer?
Andy Hayden

j'ai utilisé pandas 13.x, iloc [] [] ou iloc [,] a produit un scalaire. juste l'iloc ne fonctionne pas avec un indice négatif, comme -1
timeislove

Si vous pouvez donner un exemple de jouet démontrant cela dans la réponse, ce serait vraiment utile!
Andy Hayden

5

Les options les plus rapides / faciles que j'ai trouvées sont les suivantes. 501 représente l'index de ligne.

df.at[501,'column_name']
df.get_value(501,'column_name')

5
get_valueest obsolète maintenant (v0.21.0 RC1 (13 octobre 2017)) la référence est ici .get_value and .set_value on Series, DataFrame, Panel, SparseSeries, and SparseDataFrame are deprecated in favor of using .iat[] or .at[] accessors (GH15269)
Shihe Zhang

4

Pour les pandas 0.10, où cela ilocn'est pas possible, filtrez a DFet obtenez les premières données de ligne pour la colonne VALUE:

df_filt = df[df['C1'] == C1val & df['C2'] == C2val]
result = df_filt.get_value(df_filt.index[0],'VALUE')

s'il y a plus d'une ligne filtrée, obtenez la première valeur de ligne. Il y aura une exception si le filtre aboutit à une trame de données vide.


3
get_valueest obsolète maintenant (v0.21.0 RC1 (13 octobre 2017)) la référence est ici .get_value and .set_value on Series, DataFrame, Panel, SparseSeries, and SparseDataFrame are deprecated in favor of using .iat[] or .at[] accessors (GH15269)
Shihe Zhang

Mais iatou atne peut pas obtenir la valeur basée sur le nom de la colonne.
sivabudh

4

Je ne sais pas si c'est une bonne pratique, mais j'ai remarqué que je peux également obtenir juste la valeur en castant la série en tant que float.

par exemple

rate

3 0,042679

Nom: taux de chômage, type: float64

float(rate)

0,0426789


Cela fonctionne-t-il également avec une série multi-éléments?
Praxiteles

2

Cela n'a pas besoin d'être compliqué:

val = df.loc[df.wd==1, 'col_name'].values[0]

-1
df_gdp.columns

Index ([u'Pays ', u'Country Code', u'Indicator Name ', u'Indicator Code', u'1960 ', u'1961', u'1962 ', u'1963', u'1964 ' , u'1965 ', u'1966', u'1967 ', u'1968', u'1969 ', u'1970', u'1971 ', u'1972', u'1973 ', u'1974' , u'1975 ', u'1976', u'1977 ', u'1978', u'1979 ', u'1980', u'1981 ', u'1982', u'1983 ', u'1984' , u'1985 ', u'1986', u'1987 ', u'1988', u'1989 ', u'1990', u'1991 ', u'1992', u'1993 ', u'1994' , u'1995 ', u'1996', u'1997 ', u'1998', u'1999 ', u'2000',u'2001 ', u'2002', u'2003 ', u'2004', u'2005 ', u'2006', u'2007 ', u'2008', u'2009 ', u'2010', u'2011 ', u'2012', u'2013 ', u'2014', u'2015 ', u'2016'], dtype = 'object')

df_gdp[df_gdp["Country Code"] == "USA"]["1996"].values[0]

8100000000000.0


4
Est-ce une réponse ou une question?
Vega

4
Bienvenue dans Stack Overflow! Merci pour l'extrait de code, qui pourrait fournir une aide immédiate limitée. Une explication appropriée améliorerait considérablement sa valeur à long terme en décrivant pourquoi il s'agit d'une bonne solution au problème, et la rendrait plus utile aux futurs lecteurs ayant d'autres questions similaires. Veuillez modifier votre réponse pour ajouter des explications, y compris les hypothèses que vous avez faites.
sepehr

Malgré les votes négatifs, cette réponse m'a réellement aidé.
CONvid19
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.