假设我具有以下数据框:
0 1 2
new NaN NaN
new one one
a b c
NaN NaN NaN
如何获取一行中唯一(非NaN)值的数量,例如:
0 1 2 _num_unique_values
new NaN NaN 1
new one one 2
a b c 3
NaN NaN NaN 0
我想可能是这样的:
df['_num_unique_values'] = len(set(df.loc.tolist())) ??
答案 0 :(得分:4)
对set
使用列表理解...。
df['num_uniq'] = [len(set(v[pd.notna(v)].tolist())) for v in df.values]
df
0 1 2 num_uniq
0 new NaN NaN 1
1 new one one 2
2 a b c 3
3 NaN NaN NaN 0
您可以使用stack
,groupby
和nunique
来做到这一点。
# df.join(df.stack().groupby(level=0).nunique().to_frame('num_uniq'))
df['num_uniq'] = df.stack().groupby(level=0).nunique()
df
0 1 2 num_uniq
0 new NaN NaN 1.0
1 new one one 2.0
2 a b c 3.0
3 NaN NaN NaN NaN
另一个选择是apply
和nunique
:
df['num_uniq'] = df.apply(pd.Series.nunique, axis=1)
df
0 1 2 num_uniq
0 new NaN NaN 1
1 new one one 2
2 a b c 3
3 NaN NaN NaN 0
性能
df_ = df
df = pd.concat([df_] * 1000, ignore_index=True)
%timeit df['num_uniq'] = [len(set(v[pd.notna(v)])) for v in df.values]
%timeit df['num_uniq'] = df.stack().groupby(level=0).nunique()
%timeit df['num_uniq'] = df.apply(pd.Series.nunique, axis=1)
%timeit df['num_uniq'] = df.nunique(1)
196 ms ± 10.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
6.34 ms ± 343 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
679 ms ± 24 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
3.21 ms ± 343 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
答案 1 :(得分:4)
只需使用nunique(axis = 1)。
import numpy as np
import pandas as pd
data={0:['new','new','a',np.nan],
1:[np.nan,'one','b', np.nan],
2:[np.nan,np.nan,'c',np.nan]}
df = pd.DataFrame(data)
print(df.nunique(axis=1))
df['num_unique'] = df.nunique(axis=1)
请参阅:
答案 2 :(得分:2)
更抽象的解决方案:
df['num_uniq']=df.nunique(axis=1)
答案 3 :(得分:1)
它的速度不及set()
的Coldspeed回答,但您也可以这样做
df['_num_unique_values'] = df.T.nunique()
首先,将df
数据帧的转置与df.T
一起使用,然后使用nunique()
获取不包含NaN
的唯一值的计数。
这是作为新列添加到原始数据框的。
df
现在应该是
0 1 2 _num_unique_values
0 new nan nan 1
1 new one one 2
2 a b c 3
3 nan nan nan 0