从 Pandas 数据框中的其他列分配列值
Assign columns' value from other columns in Pandas dataframe
如何将数据框中的列指定为等于另一列if/where满足条件?
更新
问题
当满足条件时,我需要为许多列分配值(有时是该行中另一列的值)。
条件不是问题。
我需要一个有效的方法来做到这一点:
df.loc[some condition it doesn't matter,
['a','b','c','d','e','f','g','x','y']]=df['z'],1,3,4,5,6,7,8,df['p']
简化示例数据
d = {'var' : pd.Series([10,61]),
'c' : pd.Series([100,0]),
'z' : pd.Series(['x','x']),
'y' : pd.Series([None,None]),
'x' : pd.Series([None,None])}
df=pd.DataFrame(d)
条件 if var不缺失且第一个数字小于5
结果 使df.x=df.z & df.y=1
这是不起作用的伪代码,但这是我想要的。
df.loc[((df['var'].dropna().astype(str).str[0].astype(int) < 5)),
['x','y']]=df['z'],1
但我明白了
ValueError:无法使用长度不同于值的类似列表的索引器进行设置
理想输出
c var x z y
0 100 10 x x 1
1 0 61 None x None
下面的代码有效,但效率太低,因为我需要为多个列赋值。
df.loc[((df['var'].dropna().astype(str).str[0].astype(int) < 5)),
['x']]=df['z']
df.loc[((df['var'].dropna().astype(str).str[0].astype(int) < 5)),
['y']]=1
这是一种方法:
import pandas as pd
import numpy as np
d = {'var' : pd.Series([1,6]),
'c' : pd.Series([100,0]),
'z' : pd.Series(['x','x']),
'y' : pd.Series([None,None]),
'x' : pd.Series([None,None])}
df = pd.DataFrame(d)
# Condition 1: if var is not missing
cond1 = ~df['var'].apply(np.isnan)
# Condition 2: first number is less than 5
cond2 = df['var'].apply(lambda x: int(str(x)[0])) < 5
mask = cond1 & cond2
df.ix[mask, 'x'] = df.ix[mask, 'z']
df.ix[mask, 'y'] = 1
print df
输出:
c var x y z
0 100 1 x 1 x
1 0 6 None None x
如您所见,必须在赋值的两边都应用布尔掩码,并且您需要在 y
列上广播值 1
。将步骤分成多行可能更清晰。
问题已更新,编辑:更一般地说,由于一些分配依赖于其他列,而一些分配只是沿着列广播,您可以分两步完成:
df.loc[conds, ['a','y']] = df.loc[conds, ['z','p']]
df.loc[conds, ['b','c','d','e','f','g','x']] = [1,3,4,5,6,7,8]
您可以分析一下,看看这对您的用例是否足够有效。
您可以按行工作:
def f(row):
if row['var'] is not None and int(str(row['var'])[0]) < 5:
row[['x', 'y']] = row['z'], 1
return row
>>> df.apply(f, axis=1)
c var x y z
0 100 10 x 1 x
1 0 61 None NaN x
覆盖原来的df:
df = df.apply(f, axis=1)
如何将数据框中的列指定为等于另一列if/where满足条件?
更新
问题
当满足条件时,我需要为许多列分配值(有时是该行中另一列的值)。
条件不是问题。
我需要一个有效的方法来做到这一点:
df.loc[some condition it doesn't matter,
['a','b','c','d','e','f','g','x','y']]=df['z'],1,3,4,5,6,7,8,df['p']
简化示例数据
d = {'var' : pd.Series([10,61]),
'c' : pd.Series([100,0]),
'z' : pd.Series(['x','x']),
'y' : pd.Series([None,None]),
'x' : pd.Series([None,None])}
df=pd.DataFrame(d)
条件 if var不缺失且第一个数字小于5
结果 使df.x=df.z & df.y=1
这是不起作用的伪代码,但这是我想要的。
df.loc[((df['var'].dropna().astype(str).str[0].astype(int) < 5)),
['x','y']]=df['z'],1
但我明白了
ValueError:无法使用长度不同于值的类似列表的索引器进行设置
理想输出
c var x z y
0 100 10 x x 1
1 0 61 None x None
下面的代码有效,但效率太低,因为我需要为多个列赋值。
df.loc[((df['var'].dropna().astype(str).str[0].astype(int) < 5)),
['x']]=df['z']
df.loc[((df['var'].dropna().astype(str).str[0].astype(int) < 5)),
['y']]=1
这是一种方法:
import pandas as pd
import numpy as np
d = {'var' : pd.Series([1,6]),
'c' : pd.Series([100,0]),
'z' : pd.Series(['x','x']),
'y' : pd.Series([None,None]),
'x' : pd.Series([None,None])}
df = pd.DataFrame(d)
# Condition 1: if var is not missing
cond1 = ~df['var'].apply(np.isnan)
# Condition 2: first number is less than 5
cond2 = df['var'].apply(lambda x: int(str(x)[0])) < 5
mask = cond1 & cond2
df.ix[mask, 'x'] = df.ix[mask, 'z']
df.ix[mask, 'y'] = 1
print df
输出:
c var x y z
0 100 1 x 1 x
1 0 6 None None x
如您所见,必须在赋值的两边都应用布尔掩码,并且您需要在 y
列上广播值 1
。将步骤分成多行可能更清晰。
问题已更新,编辑:更一般地说,由于一些分配依赖于其他列,而一些分配只是沿着列广播,您可以分两步完成:
df.loc[conds, ['a','y']] = df.loc[conds, ['z','p']]
df.loc[conds, ['b','c','d','e','f','g','x']] = [1,3,4,5,6,7,8]
您可以分析一下,看看这对您的用例是否足够有效。
您可以按行工作:
def f(row):
if row['var'] is not None and int(str(row['var'])[0]) < 5:
row[['x', 'y']] = row['z'], 1
return row
>>> df.apply(f, axis=1)
c var x y z
0 100 10 x 1 x
1 0 61 None NaN x
覆盖原来的df:
df = df.apply(f, axis=1)