pandas 删除具有更多缺失值的重复观测

omjgkv6w  于 2023-03-28  发布在  其他
关注(0)|答案(3)|浏览(100)

我在df中有重复的值,但是其中一个观察值有很多nan。我想保留缺失值最低的重复值。
有什么办法吗?
这是我的df的一个例子:

id    B    C    D
1     2    3    4
1     .    3    4
1     .    .    4
2     9    7    .
2     9    .    8
2     9    7    8
2     .    .    .

在这个例子中,我只想保留第一个观察结果和第六个。
谢谢

f87krz0w

f87krz0w1#

您可以使用df.isna().sum(axis=1)按行计数NaNs的数量,然后使用GroupByid并使用idxmin选择NaNs较少的行:

df.loc[df.isna().sum(axis=1).groupby(df.id).idxmin(),:]

   id    B    C    D
0   1  2.0  3.0  4.0
5   2  9.0  7.0  8.0

确保缺少的值为您指定的NaNs,否则从以下内容开始:

df.replace('.',np.nan)
093gszye

093gszye2#

一种不同的方法,它比你要求的做得更多。这是如果一行中缺少一些值,另一行中缺少不同的值,你想合并这些值以获得更完整的信息:

df = pd.DataFrame({"id": [1, 1, 1, 2, 2, 2], "B": [2, np.nan, np.nan, np.nan, np.nan, 9], "C": [3, 3, np.nan, 7, np.nan, np.nan], "D": [4, 4, 4, np.nan, 8, np.nan]})
#      B    C    D  id
# 0  NaN  3.0  4.0   1
# 1  NaN  3.0  NaN   1
# 2  NaN  NaN  4.0   1
# 3  NaN  7.0  NaN   2
# 4  NaN  NaN  8.0   2
# 5  9.0  NaN  NaN   2

df.groupby("id", as_index=False).fillna(method="bfill").drop_duplicates(subset="id")
#      B    C    D  id
# 0  NaN  3.0  4.0   1
# 3  9.0  7.0  8.0   2

请注意,示例df与您的问题略有不同,以便展示这种方法在哪里更好。
对于id 1,它与只取第一行相同。但对于id 2,它实际上能够填写所有值,而您的(或其他答案)将只取一行,所有这些都很糟糕。
显然,这是假设不是NaN的值保持不变。如果它们不一样,则只取该列中第一次出现的NaN。
编辑:
在较新的pandas版本(至少1.4.2)中,fillna在应用于分组 Dataframe 时似乎会做一些奇怪的事情,并删除id列。您可以使用apply来规避此问题:

df.groupby("id", as_index=False)\
  .apply(lambda s: s.fillna(method="bfill"))\
  .drop_duplicates(subset="id")
ne5o7dgx

ne5o7dgx3#

您可以使用以下命令删除具有一定数量NaN的任何行:

df = df.dropna(axis=0, thresh=4)  # drop any row that has at least 4 non-nans within it.

axis=0为行
thresh=4是检查。您可以将其设置为任何您喜欢的值。您可以将其设置为2,以便删除任何具有2个或更多NaN的行。

相关问题