我有一个熊猫数据框:
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(' ')
答案 0 :(得分:2)
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:
代码是:
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