如何根据 python 中 select 列右侧的每行中的 nans 数量对数据帧进行子集化?
How to subset a dataframe by the number of nans in each row to the right of a select column in python?
我有一个数据框形式的订单簿,如下所示:
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”月,这意味着我只对数据框的这一部分感兴趣:
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,是否有一种有效的方法来识别哪个 ID's/indexes 有 6 个连续的单元格,其中来自列 '5' 的 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')
是否有解决此问题的替代方法?
- 创建一个名为
m
的掩码,用于过滤具有 df.iloc[:,6:11]
的那些特定列。
- 然后,您可以将
.isnull()
添加到掩码,这将根据这些列中的所有单元格是否为空来 return True 或 False。
- 掩码的最后一部分是获取
.sum
并传递 axis=1
,这将为您提供 True
的所有 sum
值26=]all columns for each row,因为True=1 and False=0,因为True/False是布尔数据type.So,m
,给你一系列所选列的真值计数。
- 最后一步是简单地根据此掩码
df = df[m == 5]
过滤器过滤整个数据帧,以过滤具有 5 个真值的行,即指定列的所有行 NaN
。
代码:
m = df.iloc[:,6:11].isnull().sum(axis=1)
df = df[m == 5]
输出:
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
我有一个数据框形式的订单簿,如下所示:
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”月,这意味着我只对数据框的这一部分感兴趣:
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,是否有一种有效的方法来识别哪个 ID's/indexes 有 6 个连续的单元格,其中来自列 '5' 的 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')
是否有解决此问题的替代方法?
- 创建一个名为
m
的掩码,用于过滤具有df.iloc[:,6:11]
的那些特定列。 - 然后,您可以将
.isnull()
添加到掩码,这将根据这些列中的所有单元格是否为空来 return True 或 False。 - 掩码的最后一部分是获取
.sum
并传递axis=1
,这将为您提供True
的所有sum
值26=]all columns for each row,因为True=1 and False=0,因为True/False是布尔数据type.So,m
,给你一系列所选列的真值计数。 - 最后一步是简单地根据此掩码
df = df[m == 5]
过滤器过滤整个数据帧,以过滤具有 5 个真值的行,即指定列的所有行NaN
。
代码:
m = df.iloc[:,6:11].isnull().sum(axis=1)
df = df[m == 5]
输出:
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