2017-10-05 89 views
1

對於我來說,這是一個相當常見的用例,我想從熊貓數據框中獲取特定值,知道如果數據沒有以某種方式被搞亂,應該只有一個值滿足特定選擇標準:從Pandas DataFrame獲取單一值,並且如果含糊不清則引發異常

我通常做的是:

myvals = df[df['criterion']=='value']['parameterofinterest'].values 
if len(myvals) != 1: 
    raise ValueError('Something messed up the data integrity.') 
myvalue = myvals[0] 

這是相當多的樣板代碼,它似乎像過基本的東西來實現的功能熊貓外。你知道是否已經有熊貓的功能,這可以幫助我在這裏。

+0

樣本數據提供給重現同樣的錯誤? – Dark

+0

它可以是任何類型的數據,其中'value'預計只會在'criterion'列出現一次。 – TheChymera

+0

你可以對所有值做初步檢查嗎?就像'(df ['criterion'] .value_counts()== 1).all()'? – IanS

回答

0

.item()是從pd.DataFrame對象的 條件選擇提取單個值的正確方法 - 同時提高異常,如果多於一個的項是否存在。

import pandas as pd 
a = [{'a':3, 'b':4},{'a':2, 'b':4}] 
c = pd.DataFrame(a) 
c[c['b']==4]['a'].values 
c[c['b']==4]['a'].item() 

引發的異常是目前:

ValueError: can only convert an array of size 1 to a Python scalar 
3

我認爲有可能的3個州 - 沒有價值 - 它返回len=0,匹配更多的值 - 它返回len>1和標量len==1

所以,你的代碼看起來正確,只有一點點進行了改進:

myvals = df.loc[df['criterion']=='value', 'parameterofinterest'] 

if len(myvals) == 1: 
    myvals = myvals.item()   
else: 
    raise ValueError('Something messed up the data integrity.') 

可以包裹功能:

def scalar_only(mask_col, val, another_col): 
    myvals = df.loc[df[mask_col]==val, another_col] 

    if len(myvals) != 1: 
     raise ValueError('Something messed up the data integrity.') 
    else: 
     return myvals.item() 

df = pd.DataFrame({'parameterofinterest': [25.0, 38.0, 34.6], 
        'criterion': ['value', 'aa', 'bb']}) 


print (scalar_only('criterion', 'value', 'parameterofinterest')) 
25.0 
df = pd.DataFrame({'parameterofinterest': [25.0, 38.0, 34.6], 
        'criterion': ['dd', 'aa', 'bb']}) 


print (scalar_only('criterion', 'value', 'parameterofinterest')) 

ValueError: Something messed up the data integrity.

df = pd.DataFrame({'parameterofinterest': [25.0, 38.0, 34.6], 
        'criterion': ['value', 'value', 'bb']}) 


print (scalar_only('criterion', 'value', 'parameterofinterest')) 

ValueError: Something messed up the data integrity.

+0

謝謝。你的版本爲什麼改進? (爲什麼使用'.loc',爲什麼使用'.item()'而不是'.values [0]'?爲什麼使用if/else當raise會終止代碼?) – TheChymera

+0

我使用'loc',因爲它是更快和推薦[檢查145](https://pandas.pydata.org/pandas-docs/stable/indexing.html#boolean-indexing)。 '.values [0]'可以替代'item()'。 – jezrael

+0

嗯,所以我的回答沒有幫助? – jezrael