是否有pandas功能允许根据条件从不同的列中进行选择?这类似于SQL Select子句中的CASE语句。例如,假设我有以下DataFrame:
foo = DataFrame(
[['USA',1,2],
['Canada',3,4],
['Canada',5,6]],
columns = ('Country', 'x', 'y')
)
我想在Country =='USA'时从列'x'中选择,在Country =='Canada'时从列'y'中选择,产生如下内容:
Country x y z
0 USA 1 2 1
1 Canada 3 4 4
2 Canada 5 6 6
[3 rows x 4 columns]
答案 0 :(得分:11)
使用DataFrame.where
' other
参数和pandas.concat
:
>>> import pandas as pd
>>>
>>> foo = pd.DataFrame([
... ['USA',1,2],
... ['Canada',3,4],
... ['Canada',5,6]
... ], columns=('Country', 'x', 'y'))
>>>
>>> z = foo['x'].where(foo['Country'] == 'USA', foo['y'])
>>> pd.concat([foo['Country'], z], axis=1)
Country x
0 USA 1
1 Canada 4
2 Canada 6
如果您希望z
作为列名,请指定keys
:
>>> pd.concat([foo['Country'], z], keys=['Country', 'z'], axis=1)
Country z
0 USA 1
1 Canada 4
2 Canada 6
答案 1 :(得分:5)
这样可行:
In [84]:
def func(x):
if x['Country'] == 'USA':
return x['x']
if x['Country'] == 'Canada':
return x['y']
return NaN
foo['z'] = foo.apply(func(row), axis = 1)
foo
Out[84]:
Country x y z
0 USA 1 2 1
1 Canada 3 4 4
2 Canada 5 6 6
[3 rows x 4 columns]
您可以使用loc
:
In [137]:
foo.loc[foo['Country']=='Canada','z'] = foo['y']
foo.loc[foo['Country']=='USA','z'] = foo['x']
foo
Out[137]:
Country x y z
0 USA 1 2 1
1 Canada 3 4 4
2 Canada 5 6 6
[3 rows x 4 columns]
修改强>
虽然使用loc
时笨拙但使用较大的数据帧会更好地扩展,因为这里的每个行都会调用apply,而使用布尔索引会进行矢量化。
答案 2 :(得分:1)
这是一个通用的解决方案,可以在另一列中选择给定值的任意列。
这样做的另一个好处是可以在简单的dict
结构中分离查找逻辑,从而可以轻松修改。
import pandas as pd
df = pd.DataFrame(
[['UK', 'burgers', 4, 5, 6],
['USA', 4, 7, 9, 'make'],
['Canada', 6, 4, 6, 'you'],
['France', 3, 6, 'fat', 8]],
columns = ('Country', 'a', 'b', 'c', 'd')
)
我扩展到一个操作,其中条件结果存储在外部查找结构中(dict
)
lookup = {'Canada': 'd', 'France': 'c', 'UK': 'a', 'USA': 'd'}
为pd.DataFrame
中存储的每个列循环dict
,并使用条件表中的值来确定要选择的列
for k,v in lookup.iteritems():
filt = df['Country'] == k
df.loc[filt, 'result'] = df.loc[filt, v] # modifies in place
给生命课
In [69]: df
Out[69]:
Country a b c d result
0 UK burgers 4 5 6 burgers
1 USA 4 7 9 make make
2 Canada 6 4 6 you you
3 France 3 6 fat 8 fat
答案 3 :(得分:0)
我的尝试:
temp1 = foo[(foo['Country'] == 'Canada')][['Country', 'y']].rename(columns={'y': 'z'})
temp2 = foo[(foo['Country'] == 'USA')][['Country', 'x']].rename(columns={'x': 'z'})
wanted_df = pd.concat([temp1, temp2])
答案 4 :(得分:0)
numpy.select非常适合该工作,尤其是有多种选择的情况。在数据帧中效果很好:
conditions = [
foo['Country'] == 'USA',
foo['Country'] == 'Canada',
]
choices = [
foo['x'],
foo['y'],
]
foo['z'] = np.select(conditions, choices, default = pd.NA)