通过检测 NaN 出现的位置,通过其他列的数学运算填充一列中的 NaN

我的数据框包含数百列。幸运的是,它们可以分为具有常规列名的两大组。第 1 组包含列 Pdc、Pdc.1、Pdc.2 .... Pdc.250。第 2 组由 Pac、Pac.1.、Pac.2 .... Pac.250 组成。请注意,每组的第一列不包含后缀编号。


我想填充所有 NaN,无论它们在哪里,使用以下规则:

第 1 组(目标列和行)列的任何行中的 NaN 将用第 2 组中的列中的值以相同的顺序填充(源列和行)乘以目标列的平均值除以源列的平均值。


为了简单起见,例如,如果 NaN 在 Pdc.25 第 10 行(第 1 组)中,则应填充为:

Pdc.25 第 10 行 = Pac.25 第 10 行 *(平均 Pdc.25 / 平均 Pac.25 )


如果 NaN 在第 2 组中,则公式如下:

Pac.30 row 15 = Pdc.30 row 15 * (mean Pac.30 / mean Pdc.30)


我写了以下代码:


df['Pdc.25'] = (df['Pdc.25'].fillna(df['Pac.25']*((df['Pdc.25'].mean()/df['Pac.25'].mean())))).to_frame()

df['Pac.30'] = (df['Pac.30'].fillna(df['Pdc.30']*((df['Pac.30'].mean()/df['Pdc.30'].mean())))).to_frame()

上面的代码工作得很好,但是对于 500 列,我必须写 500 行方程。


知道如何使它变得简单,例如,通过自动定位 NaN 并根据规则填充它们吗?


谢谢你看我的问题。


富国沪深
浏览 140回答 1
1回答

千巷猫影

.values根据您的命名约定,确保列已排序并用于对齐操作。可以.where用来填满一切。如果您想在缺少列的情况下更安全(即您有 Pac.31 但没有 Pdc.31),则映射操作的列名,以保证对齐。import pandas as pd#df = df.sort_index(axis=1)pac = df.filter(like='Pac')pdc = df.filter(like='Pdc')df_res = pd.concat([pac.where(pac.notnull(), pdc.multiply(pac.mean().div(pdc.mean().values).values).values),                    pdc.where(pdc.notnull(), pac.multiply(pdc.mean().div(pac.mean().values).values).values)                    ], axis=1)输出df_res:        Pac  Pac.1     Pac.2       Pdc     Pdc.1  Pdc.20  1.000000    6.0  3.000000  1.285714  4.952381    2.01  1.555556    1.0  2.000000  2.000000  2.000000    1.02  7.000000    6.0  3.714286  7.000000  4.952381    3.03  6.000000    7.0  5.000000  5.000000  5.000000    7.04  5.000000    2.0  3.714286  6.000000  1.650794    3.05  2.000000    7.0  4.000000  7.000000  5.000000    1.06  3.000000    4.0  3.000000  4.000000  1.000000    1.07  1.000000    5.0  3.000000  1.285714  7.000000    3.08  5.000000    5.0  6.000000  4.000000  5.000000    6.09  5.000000    2.0  3.714286  6.428571  1.000000    3.0样本数据import numpy as npdf = pd.DataFrame(np.random.choice([1,2,3,4,5,6,7, np.NaN], (10,6)),                  columns = ['Pdc', 'Pdc.1', 'Pdc.2', 'Pac', 'Pac.1', 'Pac.2'])   Pdc  Pdc.1  Pdc.2  Pac  Pac.1  Pac.20  NaN    NaN    2.0  1.0    6.0    3.01  2.0    2.0    1.0  NaN    1.0    2.02  7.0    NaN    3.0  7.0    6.0    NaN3  5.0    5.0    7.0  6.0    7.0    5.04  6.0    NaN    3.0  5.0    2.0    NaN5  7.0    5.0    1.0  2.0    7.0    4.06  4.0    1.0    1.0  3.0    4.0    3.07  NaN    7.0    3.0  1.0    5.0    3.08  4.0    5.0    6.0  5.0    5.0    6.09  NaN    1.0    3.0  5.0    2.0    NaN解释:第一步是对列进行排序,然后过滤查找以字符串'Pac'或开头的列'Pdc'。由于我们对索引进行了排序,这保证了排序是一致的(只要组中的后缀集相同)df = df.sort_index(axis=1)pac = df.filter(like='Pac')pdc = df.filter(like='Pdc')print(pac.head(3))#   Pac  Pac.1  Pac.2#0  1.0    6.0    3.0#1  NaN    1.0    2.0#2  7.0    6.0    NaNprint(pdc.head(3))#   Pdc  Pdc.1  Pdc.2#0  NaN    NaN    2.0#1  2.0    2.0    1.0#2  7.0    NaN    3.0现在我们可以做数学了。忽略.fillna逻辑,只考虑计算我们将为所有内容填充的内容。DataFrame操作对准被指数(两行和列)。您可以看到pac并pdc共享行索引,但列索引(列名称)不同,这会导致问题:pac.mean()#Pac      3.888889#Pac.1    4.500000#Pac.2    3.714286#dtype: float64pdc.mean()#Pdc      5.000000#Pdc.1    3.714286#Pdc.2    3.000000#dtype: float64pac.mean().div(pdc.mean())#Pac     NaN#Pac.1   NaN#Pac.2   NaN#Pdc     NaN#Pdc.1   NaN#Pdc.2   NaN但是,因为我们之前进行了排序,我们可以看到它们values是对齐的,所以我们安全地划分每列意味着访问值数组。这给出了每Pac列的平均值除以相应Pdc列的平均值。pac.mean().div(pdc.mean().values)#Pac      0.777778#Pac.1    1.211538#Pac.2    1.238095#dtype: float64乘法有同样的对齐问题,所以再次访问这些值,现在这给了我们一个DataFrame与子集相同的形状,如果值为空,我们应该填充:pdc.multiply(pac.mean().div(pdc.mean().values).values)#        Pdc     Pdc.1     Pdc.2#0       NaN       NaN  2.476190#1  1.555556  2.423077  1.238095#...最后,fillna逻辑完成了,where因为我们有两个DataFrames:pac.where(pac.notnull(), pdc.multiply(pac.mean().div(pdc.mean().values).values).values)可以理解为“在 pac 中使用不为空的值,否则使用计算中的值”,这正是我们想要的。我们再次需要访问.values'other'(第二个参数)的 ,where因为列名再次不同,但值是对齐的。分别为每个组执行此操作,然后将它们重新加入。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python