我有一个类似于
的数据框df = pd.DataFrame({'A': [1, np.nan,2,3, np.nan,4], 'B': [np.nan, 1,np.nan,2, 3, np.nan]})
df
A B
0 1.0 NaN
1 NaN 1.0
2 2.0 NaN
3 3.0 2.0
4 NaN 3.0
5 4.0 NaN
我如何计算A的发生次数是np.nan
但B不是np.nan
,A不是np.nan
但B是np.nan
,而A和B都不是np.nan
?
我尝试了df.groupby(['A', 'B']).count()
,但是它没有读取带有np.nan
的行。
答案 0 :(得分:6)
如果我们只处理两列,那么有一个非常简单的解决方案,涉及为A和B列分配简单的权重,然后将它们求和。
v = df.isna().mul([1, 2]).sum(1).value_counts()
v.index = v.index.map({2: 'only B', 1: 'only A', 0: 'neither'})
v
only B 3
only A 2
neither 1
dtype: int64
通过pivot_table
和stack
的另一种替代方法可以实现,
df.isna().pivot_table(index='A', columns='B', aggfunc='size').stack()
A B
False False 1.0
True 3.0
True False 2.0
dtype: float64
答案 1 :(得分:6)
使用
df.isnull().groupby(['A','B']).size()
Out[541]:
A B
False False 1
True 3
True False 2
dtype: int64
答案 2 :(得分:5)
您可以将DataFrame.isna
与crosstab
一起使用,以计算True值:
df1 = df.isna()
df2 = pd.crosstab(df1.A, df1.B)
print (df2)
B False True
A
False 1 3
True 2 0
对于标量:
print (df2.loc[False, False])
1
df2 = pd.crosstab(df1.A, df1.B).add_prefix('B_').rename(lambda x: 'A_' + str(x))
print (df2)
B B_False B_True
A
A_False 1 3
A_True 2 0
然后用于标量使用索引编制:
print (df2.loc['A_False', 'B_False'])
1
另一种解决方案是将DataFrame.dot
和列Series.replace
和Series.value_counts
一起使用:
df = pd.DataFrame({'A': [1, np.nan,2,3, np.nan,4, np.nan],
'B': [np.nan, 1,np.nan,2, 3, np.nan, np.nan]})
s = df.isna().dot(df.columns).replace({'':'no match'}).value_counts()
print (s)
B 3
A 2
no match 1
AB 1
dtype: int64
答案 3 :(得分:1)
我认为您需要:
df = pd.DataFrame({'A': [1, np.nan,2,3, np.nan,4], 'B': [np.nan, 1,np.nan,2, 3, np.nan]})
count1 = len(df[(~df['A'].isnull()) & (df['B'].isnull())])
count2 = len(df[(~df['A'].isnull()) & (~df['B'].isnull())])
count3 = len(df[(df['A'].isnull()) & (~df['B'].isnull())])
print(count1, count2, count3)
输出:
3 1 2
答案 4 :(得分:0)
要获取A或B为空的行,我们可以这样做:
bool_df = df.isnull()
df[bool_df['A'] ^ bool_df['B']].shape[0]
要获取均为空值的行:
df[bool_df['A'] & bool_df['B']].shape[0]