我在映射另一个数据框的值时遇到问题。
这些是两个数据帧的示例:
df1
product class_1 class_2 class_3
141A 11 13 5
53F4 12 11 18
GS24 14 12 10
df2
id product_type_0 product_type_1 product_type_2 product_type_3 measure_0 measure_1 measure_2 measure_3
1 141A GS24 NaN NaN 1 3 NaN NaN
2 53F4 NaN NaN NaN 1 NaN NaN NaN
3 53F4 141A 141A NaN 2 2 1 NaN
4 141A GS24 NaN NaN 3 2 NaN NaN
接下来我要获得的是: 我需要添加一个名为“ Max_Class_1”,“ Max_Class_2”,“ Max_Class_3”的新列,该值将从df1中获取。 对于每个订单号(_1,_2,_3),请查看现有列(例如product_type_1)product_type_1,并从df1中获取一行,其中产品具有相同的值。然后查看一下度量列(例如measure_1),如果该值为1(在原始数据中最多可能有四个不同的值),则新列“ Max_Class_1”的值将与该product_type的class_1相同,在这种情况下为11。
我认为这比我解释的要简单一些。
所需的输出
id product_type_0 product_type_1 product_type_2 product_type_3 measure_0 measure_1 measure_2 measure_3 max_class_0 max_class_1 max_class_2 max_class_3
1 141A GS24 NaN NaN 1 3 NaN NaN 1 10 NaN NaN
2 53F4 NaN NaN NaN 1 NaN NaN NaN 12 NaN NaN NaN
3 53F4 141A 141A NaN 2 2 1 NaN 11 13 11 NaN
4 141A GS24 NaN NaN 3 2 NaN NaN 5 12 NaN NaN
我尝试过的代码:
df2['max_class_1'] = None
df2['max_class_2'] = None
df2['max_class_3'] = None
def get_max_class(product_df, measure_df, product_type_column, measure_column, max_class_columns):
for index, row in measure_df.iterrows():
product_df_new = product_df[product_df['product'] == row[product_type_column]]
for ind, r in product_df_new.iterrows():
if row[measure_column] == 1:
row[max_class_columns] = r['class_1']
elif row[measure_column] == 2:
row[max_class_columns] = r['class_2']
elif row[measure_column] == 3:
row[max_class_columns] = r['class_3']
else:
row[tilt_column] = "There is no measure or type"
return measure_df
# And the function call
first_class = get_max_class(product_df=df1, measure_df=df2, product_type_column=product_type_1, measure_column='measure_1', max_class_columns='max_class_1')
second_class = get_max_class(product_df=df1, measure_df=first_class, product_type_column=product_type_2, measure_column='measure_2', max_class_columns='max_class_2')
third_class = get_max_class(product_df=df1, measure_df=second_class, product_type_column=product_type_3, measure_column='measure_3', max_class_columns='max_class_3')
我很确定有一个简单的解决方案,但是不知道为什么不起作用。我得到所有None值,什么都没有改变。
答案 0 :(得分:5)
pd.DataFrame.lookup
是用于按行和列标签进行查找的标准方法。
由于存在空值,您的问题变得很复杂。但这可以通过修改输入映射数据框来解决。
第1步
将df1
中的列重命名为整数,并添加额外的行/列。稍后我们将使用添加的数据处理空值。
def rename_cols(x):
return x if not x.startswith('class') else int(x.split('_')[-1])
df1 = df1.rename(columns=rename_cols)
df1 = df1.set_index('product')
df1.loc['X'] = 0
df1[0] = 0
您的映射数据框现在看起来像:
print(df1)
1 2 3 0
product
141A 11 13 5 0
53F4 12 11 18 0
GS24 14 12 10 0
X 0 0 0 0
第2步
迭代类别数并使用pd.DataFrame.lookup
。请注意,我们如何fillna
与X
和0
一起使用,这正是我们在步骤1中用于其他映射数据的方式。
n = df2.columns.str.startswith('measure').sum()
for i in range(n):
rows = df2['product_type_{}'.format(i)].fillna('X')
cols = df2['measure_{}'.format(i)].fillna(0).astype(int)
df2['max_{}'.format(i)] = df1.lookup(rows, cols)
结果
print(df2)
id product_type_0 product_type_1 product_type_2 product_type_3 measure_0 \
0 1 141A GS24 NaN NaN 1
1 2 53F4 NaN NaN NaN 1
2 3 53F4 141A 141A NaN 2
3 4 141A GS24 NaN NaN 3
measure_1 measure_2 measure_3 max_0 max_1 max_2 max_3
0 3.0 NaN NaN 11 10 0 0
1 NaN NaN NaN 12 0 0 0
2 2.0 1.0 NaN 11 13 11 0
3 2.0 NaN NaN 5 12 0 0
如果需要,可以将0
转换为np.nan
。这将以将您的系列从int
转换为float
为代价,因为NaN
被认为是float
。
当然,如果X
和0
是有效值,则可以从头开始使用替代填充值。