Python(Pandas):根据有关数据框中其他观测值的信息替换特定的 NaN 值
Python(Pandas): Replacing specific NaN values conditional on information about other observations in the dataframe
如果有一个数据框,其中每个观察都有一个标识观察的 UniqueID 和一个标识对象的 ObjectID。同一对象可以有多个观察值,即 ObjectID 不是唯一的。
一些观察结果具有变量的 Null 值,但这仅取决于对象。因此,如果一个 ObjectID 出现多次并且至少指定了一次变量,则其他观察值的 Null 值应替换为该值。
我正在使用 Python 库 Pandas (pd) 和 Numpy (np)
示例:
sample_frame = {'UniqueID': [1,2,3,4,5,6,7],"PersonID": [3,2,2,5,5,4,4], "Name":
["Alice",np.nan,"Bob","Joe","Joe",np.nan,np.nan]}
sample_frame = pd.DataFrame(data = sample_frame)
sample_frame
Index
UniqueID
PersonID
Name
0
1
3
Alice
1
2
2
Bob
2
3
2
NaN
3
4
5
Joe
4
5
5
Joe
5
6
4
NaN
6
7
4
NaN
因此,在索引为 2 的行中,Name 的 NaN 值应替换为“Bob”。
但是,下面的观察就没有办法了。
我找到了一个可行但对我来说似乎有点复杂的解决方案:
dup = sample_frame.loc[sample_frame.duplicated(subset = ["PersonID"]), :]
dup_persId = dup["PersonID"].unique()
name_na = sample_frame[sample_frame["Name"].isna()]
name_na_persId = name_na["PersonID"].unique()
dup_name_av = dup[dup["Name"].isna() == False]
dup_name_av_persId = dup_name_av["PersonID"].unique()
for i in name_na_persId:
if i in dup_name_av_persId:
index = sample_frame.index[sample_frame["PersonID"] == i].tolist()
for k in index:
if sample_frame.at[k,"Name"] is not np.nan:
name_temp = sample_frame.at[k,"Name"]
continue
for j in index:
if sample_frame.at[j,"Name"] is np.nan:
sample_frame.at[j,"Name"] = name_temp
else:
continue
有更简单的方法吗?
sample_frame['Name'].fillna(sample_frame.groupby('PersonID')['Name'].transform('first'))
通过 PersonID
使用 groupby
,然后在 Name
列上调用 .transform('first')
将 return Name
中的第一个非 NaN 值] 该行所属的组中的列。
如果有一个数据框,其中每个观察都有一个标识观察的 UniqueID 和一个标识对象的 ObjectID。同一对象可以有多个观察值,即 ObjectID 不是唯一的。
一些观察结果具有变量的 Null 值,但这仅取决于对象。因此,如果一个 ObjectID 出现多次并且至少指定了一次变量,则其他观察值的 Null 值应替换为该值。
我正在使用 Python 库 Pandas (pd) 和 Numpy (np)
示例:
sample_frame = {'UniqueID': [1,2,3,4,5,6,7],"PersonID": [3,2,2,5,5,4,4], "Name":
["Alice",np.nan,"Bob","Joe","Joe",np.nan,np.nan]}
sample_frame = pd.DataFrame(data = sample_frame)
sample_frame
Index | UniqueID | PersonID | Name |
---|---|---|---|
0 | 1 | 3 | Alice |
1 | 2 | 2 | Bob |
2 | 3 | 2 | NaN |
3 | 4 | 5 | Joe |
4 | 5 | 5 | Joe |
5 | 6 | 4 | NaN |
6 | 7 | 4 | NaN |
因此,在索引为 2 的行中,Name 的 NaN 值应替换为“Bob”。 但是,下面的观察就没有办法了。
我找到了一个可行但对我来说似乎有点复杂的解决方案:
dup = sample_frame.loc[sample_frame.duplicated(subset = ["PersonID"]), :]
dup_persId = dup["PersonID"].unique()
name_na = sample_frame[sample_frame["Name"].isna()]
name_na_persId = name_na["PersonID"].unique()
dup_name_av = dup[dup["Name"].isna() == False]
dup_name_av_persId = dup_name_av["PersonID"].unique()
for i in name_na_persId:
if i in dup_name_av_persId:
index = sample_frame.index[sample_frame["PersonID"] == i].tolist()
for k in index:
if sample_frame.at[k,"Name"] is not np.nan:
name_temp = sample_frame.at[k,"Name"]
continue
for j in index:
if sample_frame.at[j,"Name"] is np.nan:
sample_frame.at[j,"Name"] = name_temp
else:
continue
有更简单的方法吗?
sample_frame['Name'].fillna(sample_frame.groupby('PersonID')['Name'].transform('first'))
通过 PersonID
使用 groupby
,然后在 Name
列上调用 .transform('first')
将 return Name
中的第一个非 NaN 值] 该行所属的组中的列。