6

I feel like there has to be a quick solution to my problem, I hacked out a poorly implemented solution using multiple list comprehensions which is not ideal whatsoever. Maybe someone could help out here.

I have a set of values which are strings (e.g. 3.2B, 1.5M, 1.1T) where naturally the last character denotes million, billion, trillion. Within the set there are also NaN/'none' values which should remain untouched. I wish to convert these to floats or ints, so in the given example (3200000000, 1500000, 1100000000000)

TIA

4

3 回答 3

6

You could create a function: and applymap it to every entry in the dataframe:

powers = {'B': 10 ** 9, 'M': 10 ** 6, 'T': 10 ** 12}
# add some more to powers as necessary

def f(s):
    try:
        power = s[-1]
        return int(s[:-1]) * powers[power]
    except TypeError:
        return s

df.applymap(f)
于 2013-01-08T15:55:00.950 回答
3

Setup
Borrowing @MaxU's pd.DataFrame

df = pd.DataFrame({'col': ['123.456', '78M', '0.5B']})

Solution
Replace strings with scientific notation then use astype(float)

d = dict(M='E6', B='E9', T='E12')

df.replace(d, regex=True).astype(float)

            col
0  1.234560e+02
1  7.800000e+07
2  5.000000e+08
于 2017-10-04T22:37:08.783 回答
2

Demo:

In [58]: df
Out[58]:
       col
0  123.456
1      78M
2     0.5B

In [59]: d = {'B': 10**9, 'M': 10**6}

In [60]: df['new'] = \
    ...: df['col'].str.extract(r'(?P<val>[\d.]+)\s*?(?P<mult>\D*)', expand=True) \
    ...:   .replace('','1') \
    ...:   .replace(d, regex=True) \
    ...:   .astype(float) \
    ...:   .eval('val * mult')
    ...:

In [61]: df
Out[61]:
       col           new
0  123.456  1.234560e+02
1      78M  7.800000e+07
2     0.5B  5.000000e+08
于 2017-10-04T22:25:58.020 回答