根据条件从数据框中选择行
Selecting rows from a dataframe based on conditions
我有一个数据框:
>>> 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 在 Val 列中具有 'High' 的行 select 在 '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 列的数据框。
编辑添加
真正的 pandonic 方法是使用 categories:
>>> 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
,所以首先,创建映射您的 "High"、"Mod" 和 [= 的列45=] 值到 数字 以便我们可以理智而轻松地使用它们:
>>> 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
当然,您始终可以 select 您特别想要的列:
>>> (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
所以,如果您考虑一下您的要求:
"where for the same IDs in the first column, " => 使用 groupby('ID')
"gives high precedence to 'High' value than 'Low' or 'Mod' and then from among the rows for that ID with 'High' in the Val column select the row with higher value in the 'Num' column." => 按 Val 排序,然后按 Num(降序)排序,然后取最高的。
我有一个数据框:
>>> 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 在 Val 列中具有 'High' 的行 select 在 '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 列的数据框。
编辑添加
真正的 pandonic 方法是使用 categories:
>>> 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
,所以首先,创建映射您的 "High"、"Mod" 和 [= 的列45=] 值到 数字 以便我们可以理智而轻松地使用它们:
>>> 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
当然,您始终可以 select 您特别想要的列:
>>> (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
所以,如果您考虑一下您的要求:
"where for the same IDs in the first column, " => 使用 groupby('ID')
"gives high precedence to 'High' value than 'Low' or 'Mod' and then from among the rows for that ID with 'High' in the Val column select the row with higher value in the 'Num' column." => 按 Val 排序,然后按 Num(降序)排序,然后取最高的。