簡體   English   中英

如何通過 python 中 select 列右側的每行中的 nan 數對 dataframe 進行子集化?

[英]How to subset a dataframe by the number of nans in each row to the right of a select column in python?

我有一個 dataframe 形式的訂單簿,如下所示:

import pandas as pd
import numpy as np

months = list(range(1, 13))
li = list(map(str, months))
cols = ['ID']
cols.extend(li)

df = pd.DataFrame(np.random.randint(0,1000,size=(10, 13)), columns=cols)
df.loc[[1,2],'1':'12'] = np.nan
df.loc[3,'7':'12'] = np.nan
df.loc[5,'5':'12'] = np.nan
df.loc[7,'3':'8'] = np.nan
df.loc[9,'3':'10'] = np.nan

    ID      1      2      3      4      5      6      7      8      9     10     11     12
0  328   45.0  226.0  388.0  286.0  557.0  930.0  234.0  418.0  863.0  500.0  232.0  116.0
1  340    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN
2  865    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN
3  313  947.0  272.0  936.0  501.0  241.0  731.0    NaN    NaN    NaN    NaN    NaN    NaN
4  293  772.0  185.0    6.0  284.0  522.0  826.0  995.0  370.0   87.0  668.0  469.0   40.0
5  226   31.0  994.0  896.0  889.0    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN
6  622  128.0  337.0   67.0  763.0  999.0  853.0  172.0  927.0  460.0  602.0  134.0  115.0
7  454  407.0    1.0    NaN    NaN    NaN    NaN    NaN    NaN   33.0   60.0  112.0  127.0
8  538  968.0  924.0  113.0  162.0  416.0   16.0   88.0  631.0  516.0  593.0   65.0  574.0
9  501  949.0  709.0    NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN  272.0  220.0

就目前而言,我遍歷列然后遍歷行,根據左側單元格中的值填充每個單元格。

假設我在“5”月,這意味着我只對 dataframe 的這一部分感興趣:

    ID       5      6      7      8      9     10     11     12
0  328     557.0  930.0  234.0  418.0  863.0  500.0  232.0  116.0
1  340       NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN
2  865       NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN
3  313     241.0  731.0    NaN    NaN    NaN    NaN    NaN    NaN
4  293     522.0  826.0  995.0  370.0   87.0  668.0  469.0   40.0
5  226       NaN    NaN    NaN    NaN    NaN    NaN    NaN    NaN
6  622     999.0  853.0  172.0  927.0  460.0  602.0  134.0  115.0
7  454       NaN    NaN    NaN    NaN   33.0   60.0  112.0  127.0
8  538     416.0   16.0   88.0  631.0  516.0  593.0   65.0  574.0
9  501       NaN    NaN    NaN    NaN    NaN    NaN  272.0  220.0

並給定一個變量 term_len = 6,是否有一種有效的方法可以從“5”列中識別哪些 ID/索引有 6 個連續單元格,其中包含 NaN?

我期望的是要識別的行 [1, 2, 5, 9]。 不是索引 4,因為它只有 4 個 NaN,也不是索引 3,因為該行不以 NaN 開頭。

我能想到的唯一方法是:

month = 5
subset = df.loc[:, str(month):]
term_len  = 6
idxs = pd.to_numeric(subset.apply(pd.Series.first_valid_index,axis=1))
idxsT = idxs - month - term_len
idxsT.index[(idxsT >= 0) | (idxsT.isna())]

Out: Int64Index([1, 2, 5, 9], dtype='int64')

有沒有解決這個問題的替代方法?

  1. 創建一個名為m的掩碼,使用df.iloc[:,6:11]過濾那些特定列。
  2. 然后,您可以將.isnull()添加到掩碼中,這將為這些列中的所有單元格返回 True 或 False,具體取決於它們是否為 null。
  3. 掩碼的最后一部分是獲取.sum並傳遞axis=1 ,這將為您提供每行所有列的所有True值的sum ,因為 True=1 和 False=0,因為 True/False 是一個 boolean 數據類型。因此, m為您提供所選列的 True 值的一系列計數。
  4. 最后一步是簡單地過濾整個 dataframe 基於此掩碼df = df[m == 5]過濾器以過濾具有 5 個 True 值的行,即指定列的所有行都是NaN

代碼:

m = df.iloc[:,6:11].isnull().sum(axis=1)
df = df[m == 5]

output:

    ID  1       2       3   4   5   6   7   8   9   10  11      12
1   340 NaN     NaN     NaN NaN NaN NaN NaN NaN NaN NaN NaN     NaN
2   865 NaN     NaN     NaN NaN NaN NaN NaN NaN NaN NaN NaN     NaN
5   226 31.0    994.0   896.0   889.0   NaN NaN NaN NaN NaN     NaN NaN NaN
9   501 949.0   709.0   NaN NaN NaN NaN NaN NaN NaN NaN 272.0   220.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM