我有一个数据框:
>>> d = {'ID' : ['ABC', 'ABC', 'ABC', 'DFG', 'DFG', 'DFG', 'EGF', '2BD', '2BD'], 'Val': ['High', 'Low', 'High', 'High', 'High', 'Low', 'Low', 'Low', 'High'],
... 'Num': [22,2,16,10,50,3,2,34,2], 'Val2':['Low', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High']}
>>> import pandas as pd
>>> df = pd.DataFrame(d)
>>> df
ID Num Val Val2
0 ABC 22 High Low
1 ABC 2 Low High
2 ABC 16 High Low
3 DFG 10 High High
4 DFG 50 High High
5 DFG 3 Low High
6 EGF 2 Low High
7 2BD 34 Low High
8 2BD 2 High High
是否有办法将条件应用于列中具有相同值的行,然后应用某些条件来检查其他列中的值?
我想要这样的输出:
ID | Val | Num | Val2
ABC | High | 22 | Low
DFG | High | 50 | High
EGF | Low | 2 | High
2BD | High | 2 | High
即,对于第一列中相同ID的位置,它检查Val列,优先于'High'值而不是'Low'或'Mod',然后从该ID中的行中选择'High'在Val列中,在“Num”列中选择值较高的行。
我这样做:
import pandas as pd
d = {'ID' : ['ABC', 'ABC', 'ABC', 'DFG', 'DFG', 'DFG', 'EGF', '2BD', '2BD'], 'Val': ['High', 'Low', 'High', 'High', 'High', 'Low', 'Low', 'Low', 'High'], 'Num': [22,2,16,10,50,3,2,34,2], 'Val2':['Low', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High']}
df = pd.DataFrame(d)
print df
x = df.ID.unique().tolist()
f_df=pd.DataFrame()
idlist=[]
vallist=[]
numlist=[]
for i in x:
idlist.append(i)
new_df = df.loc[df['ID'] == i]
h_df = new_df.loc[df['Val'] == 'High']
if h_df.empty:
m_df = new_df.loc[df['Val'] == 'Mod']
if m_df.empty:
l_df = new_df.loc[df['Val'] == 'Low']
vallist.append('Low')
if len(l_df) > 1:
m = l_df['Num'].max()
numlist.append(m)
else:
m = l_df['Num'].max()
numlist.append(m)
else:
vallist.append('Mod')
if len(m_df) > 1:
m = m_df['Num'].max()
numlist.append(m)
else:
m = m_df['Num'].max()
numlist.append(m)
else:
vallist.append('High')
if len(h_df) > 1:
m = h_df['Num'].max()
numlist.append(m)
else:
m = h_df['Num'].max()
numlist.append(m)
f_df['ID'] = idlist
f_df['Val'] = vallist
f_df['Num'] = numlist
print f_df
有更好的方法吗?另外,如何在输出中获得Val2
的相应值?因为我实际上有一个包含12列的数据框。
答案 0 :(得分:0)
真正的 pandonic 方法是使用类别:
>>> df['Val'] = df.Val.astype('category').cat.set_categories(['High','Mod','Low'], ordered=True)
>>> df['Val2'] = df.Val2.astype('category').cat.set_categories(['High','Mod','Low'], ordered=True)
>>> df
ID Num Val Val2
0 ABC 22 High Low
1 ABC 2 Low High
2 ABC 16 High Low
3 DFG 10 High High
4 DFG 50 High High
5 DFG 3 Low High
6 EGF 2 Low High
7 2BD 34 Low High
8 2BD 2 High High
>>> df.dtypes
ID object
Num int64
Val category
Val2 category
dtype: object
所以现在排序是我们想要的!
>>> (df.sort_values(['Val','Num'], ascending=[True, False])
... .groupby('ID')
... .nth(0))
Num Val Val2
ID
2BD 2 High High
ABC 22 High Low
DFG 50 High High
EGF 2 Low High
是的,我认为您不想使用内置排序和groupby
,因此首先要创建将“高”,“模”和“低”值映射到的列数字所以我们可以很容易地和他们一起工作:
>>> df['valmap'] = df.Val.map({'High':0, 'Mod':1, 'Low':2})
>>> df['val2map'] = df.Val2.map({'High':0, 'Mod':1, 'Low':2})
>>> df
ID Num Val Val2 valmap val2map
0 ABC 22 High Low 0 2
1 ABC 2 Low High 2 0
2 ABC 16 High Low 0 2
3 DFG 10 High High 0 0
4 DFG 50 High High 0 0
5 DFG 3 Low High 2 0
6 EGF 2 Low High 2 0
7 2BD 34 Low High 2 0
8 2BD 2 High High 0 0
然后我想你只想:
>>> df.sort_values(['valmap','Num'], ascending=[True, False]).groupby('ID').nth(0)
Num Val Val2 val2map valmap
ID
2BD 2 High High 0 0
ABC 22 High Low 2 0
DFG 50 High High 0 0
EGF 2 Low High 0 2
当然,您可以随时选择您想要的列:
>>> (df.sort_values(['valmap','Num'], ascending=[True, False])
... .groupby('ID')['Num','Val', 'Val2']
... .nth(0))
Num Val Val2
ID
2BD 2 High High
ABC 22 High Low
DFG 50 High High
EGF 2 Low High
所以,如果你考虑你的要求:
“第一列中相同ID的位置,”=>使用groupby('ID')
“优先于'High'值而不是'Low'或'Mod',然后从Val列中的'High'行中选择'Num'列中值较高的行。 “ =>按Val排序,然后按Num(降序)排序,然后取最高值。