字典键,用字典值替换pandas dataframe列中的字符串并执行评估

时间:2019-07-18 15:52:01

标签: python pandas

我有一个熊猫数据框:

df = pd.DataFrame({'col1': ['3 a, 3 ab, 1 b',
                            '4 a, 4 ab, 1 b, 1 d',
                            np.nan] })

和字典

di = {'a': 10.0,
 'ab': 2.0,
    'b': 1.5,
    'd': 1.0,
    np.nan: 0.0}

使用字典中的值,我要像这样评估数据框行:

3 * 10.0 + 3 * 2.0 + 1 * 1.5给我最终的输出像这样:

pd.DataFrame({'col1': ['3 a, 3 ab, 1 b',
                            '4 a, 4 ab, 1 b, 1 d',
                            'np.nan'], 'result': [37.5,
                            50.5,
                            0]  })

到目前为止,我只能将','替换为'+'

df['col1'].str.replace(',',' +').str.split(' ')

5 个答案:

答案 0 :(得分:2)

  1. 我们首先使用this函数将您的字符串explode {}分隔为逗号分隔的行。

  2. 然后我们用空格(' 'split分隔列。

  3. 最后我们map将您的字典放入字母中并进行groupby.sum

new  = explode_str(df.dropna(), 'col1', ',')['col1'].str.strip().str.split(' ', expand=True).append(df[df['col1'].isna()])

s = new[1].map(di) * pd.to_numeric(new[0])

df['result'] = s.groupby(s.index).sum()

输出

                  col1  result
0       3 a, 3 ab, 1 b    37.5
1  4 a, 4 ab, 1 b, 1 d    50.5
2                  NaN     0.0

链接答案中使用的功能:

def explode_str(df, col, sep):
    s = df[col]
    i = np.arange(len(s)).repeat(s.str.count(sep) + 1)
    return df.iloc[i].assign(**{col: sep.join(s).split(sep)})

答案 1 :(得分:2)

这里似乎已经结束了

df['col1'].str.split(', ',expand=True).replace({' ':'*','np.nan':'0'},regex=True).\
     stack().apply(lambda x : eval(x,di)).sum(level=0)
Out[884]: 
0    37.5
1    50.5
2     0.0
dtype: float64

答案 2 :(得分:2)

理解力

from functools import reduce
from operator import mul

def m(x): return di.get(x, x)

df.assign(result=[
    sum(
        reduce(mul, map(float, map(m, s.split())))
        for s in row.split(', ')
    ) for row in df.col1
])

                  col1  result
0       3 a, 3 ab, 1 b    37.5
1  4 a, 4 ab, 1 b, 1 d    50.5
2               np.nan     0.0

答案 3 :(得分:0)

首先,您可以从字典中插入键:

for key in di.keys():
    df['col1'] = df['col1'].str.replace(key, '*' + str(di[key]))

然后您可以插入运算符:

df['col1'] = df['col1'].str.replace(',', '+')

然后您进行评估:

df['result'] = df['col1'].apply(eval)

请注意,这可能会对np.nan有所帮助,因为其中有a被字典拾取。在那里,您可能需要事先创建其他规则,例如:

df['col1'] = df['col1'].str.replace('np.nan', '0')

答案 4 :(得分:0)

从定义一个函数替换源字符串开始 来自 di 的相应值(即将应用):

def repl(src):
    return di[src] if src in di else 0.0

然后创建一个辅助DataFrame:

  • 提取所有成对的正则表达式组:
    • n1 -一个数字序列,
    • n2 -字母或点的序列(也匹配 np.nan )。
  • n1 列更改为数字。
  • repl 函数应用于 n2 ,以替换例如'a'(字符串)与 10.0 (一个数字)。

代码是:

df2 = df.col1.str.extractall(r'(?P<n1>\d+)? ?(?P<n2>[a-z.]+)').fillna('0')
df2.n1 = pd.to_numeric(df2.n1)
df2.n2 = df2.n2.apply(repl)

并得到以下结果:

         n1    n2
  match          
0 0       3  10.0
  1       3   2.0
  2       1   1.5
1 0       4  10.0
  1       4   2.0
  2       1   1.5
  3       1   1.0
2 0       0   0.0

要获得每个组的产品总数,请运行:

df2.groupby(level=0).apply(lambda gr: gr.product(axis=1).sum())

结果是:

0    37.5
1    50.5
2     0.0