Python 如何根据与值的辅助数据框匹配的条件在主数据框的列中填充NAN,以使用多个填充值填充NAN

Python 如何根据与值的辅助数据框匹配的条件在主数据框的列中填充NAN,以使用多个填充值填充NAN,python,pandas,nan,Python,Pandas,Nan,我需要根据由groupby和mean函数创建的第二个数据帧,在我的主数据帧中填充NA值。我的原始数据帧有大约1.5K个NAN需要填充,因此这需要在大规模复制。我创建了一个假数据框,它是使用假场景对我的数据进行的一个简短、快速、肮脏的模仿。我不能和你分享我的真实数据 我的总体想法是: main_data[ (main_data["Animal_Type"] == mean_data["Animal_Type"]) &

我需要根据由
groupby
mean
函数创建的第二个数据帧,在我的主数据帧中填充NA值。我的原始数据帧有大约1.5K个NAN需要填充,因此这需要在大规模复制。我创建了一个假数据框,它是使用假场景对我的数据进行的一个简短、快速、肮脏的模仿。我不能和你分享我的真实数据

我的总体想法是:

main_data[
          (main_data["Animal_Type"] == mean_data["Animal_Type"]) & 
          (main_data["Cost_Type"] == mean_data["Cost_Type"])
         ] = main_data["Price"].fillna(mean_data["Price"])
显然,这是行不通的,但这是我的逻辑如何运作的基本要点。我找到了[他的答案][1],但我看不出能把它恰当地应用到我的问题上。很多答案都涉及到
mask
,或者假设我的数据非常小,只有一个值来替换所有的NaN。在我的原始数据集中,我有大约50种不同的方法,每种“成本类型”都与“动物类型”唯一配对。我的原始数据框大约有30K个观测值,也充满了独特的观测值。我可以映射,但这只适用于单个列。我对编码相当陌生,所以很多其他的答案对我来说太复杂了,我也太理解和修改了

主数据

mean_data.head(10)

   **Pet_ID Animal_Type Cost_Type   Price**
0   101     Goat        Housing     6.0
1   102     Dog         Housing     6.0
2   103     Horse       Housing     NaN
3   104     Horse       Housing     5.0
4   105     Goat        Housing     3.0
5   106     Dog         Feeding     3.0
6   107     Cat         Feeding     6.0
7   108     Horse       Housing     6.0
8   109     Hamster     Feeding     5.0
9   110     Horse       Feeding     3.0
平均值数据

    Animal_Type Cost_Type   Price
0   Cat         Feeding     4.500000
1   Cat         Housing     5.000000
2   Chicken     Feeding     5.000000
3   Chicken     Housing     4.500000
4   Dog         Feeding     3.000000
5   Dog         Housing     6.000000
6   Goat        Feeding     5.000000
7   Goat        Housing     5.000000
8   Hamster     Feeding     5.250000
9   Hamster     Housing     3.000000
10  Horse       Feeding     3.500000
11  Horse       Housing     5.666667
12  Rabit       Feeding     3.000000
13  Rabit       Housing     3.000000
我的可复制代码:

random.seed(10)

random.seed(10)

main_data = pd.DataFrame(columns = ["Pet_ID", "Animal_Type", "Cost_Type", "Price", "Cost"])

main_data["Pet_ID"] = pd.Series(list(range(101,150)))
main_data["Animal_Type"] = main_data.Animal_Type.apply(lambda x: random.choice(["Dog", "Cat", "Rabit", "Horse", "Goat", "Chicken", "Hamster"])) 
main_data["Cost_Type"] = main_data.Animal_Type.apply(lambda x: random.choice(["Housing", "Feeding"])) 
main_data["Price"] = main_data.Price.apply(lambda x: random.choice([3, 5, 6, np.nan])) 
main_data["Cost"] =  main_data.Cost.apply(lambda x: random.choice([2, 1, 3, np.nan])) 

mean_data = main_data.groupby(["Animal_Type", "Cost_Type"])["Price"].mean().reset_index()
编辑:我已经提出了两种解决方案,但我不会说它更优雅或更可靠。可能也不是最有效的

main_data = pd.merge(
    main_data,
    mean_data,
    on = ["Animal_Type", "Cost_Type"],
    how = "left"
)

main_data["Price_z"] = main_data["Price_x"].fillna(main_data["Price_y"])
编辑2:我添加了一个带有NAN的“成本”列。我不想触动这个专栏,但我想使用我们在价格专栏中使用的方法。 [1] :

我需要根据由
groupby
mean
函数创建的第二个数据帧,在我的主数据帧中填充NA值

你不需要那一步。您可以在一个步骤中完成这项工作,方法是将数据分组到多个数据帧中,对每个单独的数据帧应用平均值,并仅在该数据帧中填充NA值

因此,不要创建
mean_data
dataframe,而是执行以下操作:

def填充平均值(df):
df[“价格”]=df[“价格”].fillna(df[“价格”].mean())
返回df
主数据=主数据。分组依据([“动物类型”,“成本类型])。应用(按平均值填写)
每次调用fill_by_mean()都会看到一个如下所示的数据帧:

    Pet_ID Animal_Type Cost_Type  Price
11     112       Rabit   Feeding    NaN
34     135       Rabit   Feeding    3.0
38     139       Rabit   Feeding    3.0

然后它得到price列的平均值,并使用该值填充NA值。Groupby然后将所有单独的数据帧连接在一起。

@the.B第二个数据帧是我通过group by函数创建的,并在两级分组后取平均值。不幸的是,我不能将唯一标识符用于这一个。@B我认为concat不能用于不同长度的数据帧。但是我也只需要替换NaN,而不是整个列。您是否尝试过fillna()是的,我用我刚刚提出的解决方案进行了编辑,但我真的不想在我的数据框中附加/添加新列。我只想遍历该列,并根据其他两列的匹配情况插入这些值。我担心这不是最可靠的方法——至少是我想出的方法——删除你不需要的专栏。我真的很感激这个答案,但有没有办法把这个答案写在标有“Pirce”的专栏里。它帮助很大,但它也在其他列中填充了我的NAs的其余部分。我有两个关于NAs的特定列,我希望在其他列中保留NAs的同时应用这个答案,因为这些列不能用我将用其他方法填充的相同平均值方法填充。如果有帮助的话,我已经添加了一个“成本”栏any@EX_Tenn是的,您只需要在执行fillna之前选择列。请参见编辑。