所以我昨天开始提出一个问题:Multiple assignment in pandas based on the values in the same row,我想知道如何对一行数据进行排名并将排名分配给同一行中的不同列。我已经按照Ed Chum的建议想出了如何做到这一点: how to apply a function to multiple columns in a pandas dataframe at one time。
它实际上有效,但后来我注意到我在创建错误的列。一旦我修复了这个bug,就不再适用了....
所以我试图在一个玩具示例中重新创建问题,而且它也不适用于玩具示例。有人可以指出我的错误,这里是代码(python 3):
import pandas as pd
import numpy as np
import scipy
df = pd.DataFrame(data={'a':[1,2,3],'b':[2,1,3],'c':[3,1,2],
'rank_a':[np.nan]*3,'rank_b':[np.nan]*3,'rank_c':[np.nan]*3})
def apply_rank(row):
vals = [row['a'],row['b'],row['c']]
ranked = scipy.stats.rankdata(vals)
d = len(vals)+1
ranked = [rank/d for rank in ranked]
rank_cols = [col for col in row.index if col.startswith("rank_")]
print("ranked: "+str(ranked))
for idx,rank_col in enumerate(rank_cols):
print("Before: "+str(row[rank_col]))
row[rank_col] = ranked[idx]
print("After: "+str(row[rank_col]))
然后运行:
df.apply(lambda row: apply_rank(row),axis=1)
,以确保分配正确完成。
然后运行:
df
看到没有分配任何内容.. facepalm
答案 0 :(得分:1)
您可以使用新列值的索引返回Series
:
def apply_rank(row):
vals = [row['a'],row['b'],row['c']]
ranked = scipy.stats.rankdata(vals)
d = len(vals)+1
ranked = [rank/d for rank in ranked]
rank_cols = [col for col in row.index if col.startswith("rank_")]
return pd.Series(ranked, index=rank_cols)
df = df.apply(lambda row: apply_rank(row),axis=1)
print (df)
rank_a rank_b rank_c
0 0.250 0.500 0.750
1 0.750 0.375 0.375
2 0.625 0.625 0.250
编辑:如果之前存在新列,则可以向他们追加数据并返回row
:
def apply_rank(row):
vals = [row['a'],row['b'],row['c']]
ranked = scipy.stats.rankdata(vals)
d = len(vals)+1
ranked = [rank/d for rank in ranked]
rank_cols = [col for col in row.index if col.startswith("rank_")]
row.loc[rank_cols] = ranked
return row
df = df.apply(apply_rank,axis=1)
print (df)
a b c rank_a rank_b rank_c
0 1.0 2.0 3.0 0.250 0.500 0.750
1 2.0 1.0 1.0 0.750 0.375 0.375
2 3.0 3.0 2.0 0.625 0.625 0.250
答案 1 :(得分:0)
df[col].iloc[[2,3,4] = 2
在数据框df中,对于列(2,3,4),在特定列名称col处,我们可以将值设置为2,如上所示