2016-09-29 6 views
1

정수와 혼합 분수가 혼합 된 문자열 열이있는 데이터 프레임이 있습니다. 열 'y'를 부동으로 변환하고 싶습니다.데이터 프레임 열의 혼합 숫자 문자열을 분할하여 부동 소수점으로 변환

x   y   z 
0   4  Info 
1  8 1/2  Info 
2   3/4  Info 
3   10  Info 
4   4  Info 
5  6 1/4  Info 

내가 고려하고 논리 '에 의해'Y ''와 '열을 분할하는 것입니다 /'과 같을 것이다 세 개의 열을 만듭니다. 여기에서

x   base  b  c   z 
0   4  0  0  Info 
1   8  1  2  Info 
2   0  3  4  Info 
3   10  0  0  Info 
4   4  0  0  Info 
5   6  1  4  Info 

나는

def convertReplace(df): 
    convert = lambda x: float(x) 
    df['base'].apply(convert) 
    df['b'].apply(convert) 
    df['c'].apply(convert) 
    decimal = lambda x,y: x/y   
    try: 
     df['d'] = decimal(df['b'],df['c']) 
     df['y'] = df['base'] + df['d'] 
    except: 
     df['y'] = df['base'] 
    return df 

이 작동 할 수도 있지만이 방법을 사용하여 분할 열이 here를 찾을 수 없습니다.

df = pd.DataFrame(df.y.str.split(' ',1).str.split('/',1).tolist(),columns = ['base','b','c']) 

오류는 3 인자가 1, 2, 3은 심지어 this thread 여러 분리기를 사용하지 않는 수 있습니다 때마다 기대했다.

실제 데이터 프레임에는 400,000 개가 넘는 행이 있습니다. 효율성은 좋겠지 만 좀 더 관심있게 생각합니다. 이 논리가 맞습니까? 아니면이를 위해보다 간결한 방법이 있습니까? 어떤 도움을 주셔서 감사합니다.

답변

1

fractions 모듈을 사용해보십시오.

import fractions 
df['y_float'] = df['y'].apply(lambda frac: float(sum([fractions.Fraction(x) for x in frac.split()]))) 

이 제공 : 다음은 한 줄입니다

나는 위의 접근 방식을 실현 : 부정적인 분수뿐만 아니라 잘못된 텍스트를 차지 [편집] 수정 버전

 y  z y_float 
0  4 Info  4.00 
1 8 1/2 Info  8.50 
2 3/4 Info  0.75 
3  10 Info 10.00 
4  4 Info  4.00 
5 6 1/4 Info  6.25 

부정적인 분수에는 효과가 없으므로 여기에 설명되어 있습니다. 그것이 밝혀지면서, 이것에 대한 하나의 라이너는 매우 까다로울 것입니다!
def get_sign(num_str): 
    """ 
    Verify the sign of the fraction 
    """ 
    return 1-2*num_str.startswith('-') 

def is_valid_fraction(text_str): 
    """ 
    Check if the string provided is a valid fraction. 
    Here I just used a quick example to check for something of the form of the fraction you have. For something more robust based on what your data can potentially contain, a regex approach would be better. 
    """ 
    return text_str.replace(' ', '').replace('-', '').replace('/', '').isdigit() 

def convert_to_float(text_str): 
    """ 
    Convert an incoming string to a float if it is a fraction 
    """ 
    if is_valid_fraction(text_str): 
     sgn = get_sign(text_str) 
     return sgn*float(sum([abs(fractions.Fraction(x)) for x in text_str.split()])) 
    else: 
     return pd.np.nan # Insert a NaN if it is invalid text 

그래서 지금 당신이있을 것이다 :

>>> df['y_float'] = df['y'].apply(lambda frac: convert_to_float(frac)) 
>>> df 
       y  z y_float 
0    4 Info  4.00 
1   8 1/2 Info  8.50 
2   3/4 Info  0.75 
3   10 Info 10.00 
4    0 Info  0.00 
5   6 1/4 Info  6.25 
6  -3 2/5 Info -3.40 
7   -4/5 Info -0.80 
8 gibberish100 Info  NaN 
+0

나는이 작업을 거라고 생각하지만 내 실제 데이터가 조금 진흙 투성이입니다. 몇 가지 값에는 텍스트가 포함됩니다. 어떻게 이것을 적용 할 수 있지만 분수 모듈이 실행되는 유효하지 않은 리터럴을 건너 뛰는가? 형식 검사를위한 if-else 검사가 있습니까? 이 경우 'loc'명령을 사용합니까? –

+0

부정적인 분수와 진흙 투성이 텍스트를 해결하기위한 솔루션을 업데이트했습니다. – vk1011

+0

그레이트! 이것은 정말로 도움이되었습니다. @ vk1011 감사합니다! –

관련 문제