python - 根据熊猫中的条件填充数据框列
问题描述
我有两个数据框,如下所示
df_input df_output
id POLL_X POLL_Y POLL_Z .. id Pass_01 Pass_02 Pass_03 .....
110101 1 2 4 110101
110102 2 1 3 110102
并且要求是根据 df_input 中的值填写 df_ouput
df_input df_output
id POLL_X POLL_Y POLL_Z .... id Pass_01 Pass_02 Pass_03 .....
110101 1 2 3 110101 X Y Z
110102 2 1 3 110102 Y X Z
所以基本上来自 df_input 的列值将是 df_output 中的单元格值,而匹配并基于 df_input.id == df_output.id
我正在尝试如下
def function1(df_input, number):
dfwithCols = df_input[df_input.columns[pd.Series(df_input.columns).str.startswith('POLL_')]]
list_cols = dfwithCols .columns[(dfwithCols == float(number)).iloc[0]]
colValue = (dfReduced == float(index)).idxmax(axis=1)[0]
return colValue
--驱动功能--
for i in range(1,number_of_columnswithPass):
df_output['Pass_'+i] = function1(df_input,i)
number_of_columnsiwthPass 是常量,它给出名称为 pass 的总列数。
此外,我不能遍历每一行,因为这将花费大量时间,必须在基于列或基于 lambda 的情况下进行
两个数据框中还有其他列,也必须匹配 df_input.id == df_output.id
列的总数可以在 40 左右,一些测试值包括 POLL_DNW 、 POLL_DO、 POLL_DOES 、 POLL_SIG:2
所以我必须取 '_' 之后的任何内容以及 01,02,03,04 之类的列号- --10,11,--21,---39,40
解决方案
我假设一开始你的df_output有正确的列名(因为它们应该在填充之后)。
完成你的任务:
import re
(稍后会用到)。根据源行定义以下生成输出行的函数:
def genRow(row): ind = [] vals = [] for k, v in row.iteritems(): mtch = re.match('POLL_(.+)', k) if mtch: ind.append('Pass_' + str(v).zfill(2)) vals.append(mtch.group(1)) else: ind.append(k) vals.append(v) return pd.Series(vals, index=ind).rename(row.name)
请注意,此函数用相应的Pass_...列“替换”任何POLL_...列,并使其他列保持原样。
应用它:
df_output = df_input.apply(genRow, axis=1).reindex(columns=df_output.columns)
脚步:
df_input.apply(...)
- 生成“初步”输出 DataFrame。请注意,现在列顺序是按字母顺序排列的。reindex(...)
- 使用 df_output 中的列名重新索引上述 DataFrame ,提供正确的列顺序。df_output =
-用上述结果覆盖df_output 。
编辑
如果您的输入 DataFrame 在POLL_...列中包含重复值,则需要稍作修改。这种情况会导致这两个(或更多)元素具有 相同索引的输出行,因此如果包含这样的行,则无法构造整个 DataFrame。
补救措施是将这些元素“压缩”成一个具有原始索引的元素,并将所有值转换为字符串,例如包含逗号分隔的原始值列表。
为此,请将 genRow函数中的最后一行更改为:
out = pd.Series(vals, index=ind).rename(row.name)
return out.groupby(lambda key: key).apply(lambda lst: (', '.join(sorted(lst))))