给定一个带有一个描述性列和X个数字列的数据框,对于每一行,我希望识别具有较高值的前N列,并将其保存为新数据帧上的行。
例如,请考虑以下数据框:
df = pd.DataFrame()
df['index'] = ['A', 'B', 'C', 'D','E', 'F']
df['option1'] = [1,5,3,7,9,3]
df['option2'] = [8,4,5,6,9,2]
df['option3'] = [9,9,1,3,9,5]
df['option4'] = [3,8,3,5,7,0]
df['option5'] = [2,3,4,9,4,2]
我想输出(假设N是3,所以我想要前三名):
A,option3
A,option2
A,option4
B,option3
B,option4
B,option1
C,option2
C,option5
C,option4 (or option1 - ties arent really a problem)
D,option5
D,option1
D,option2
and so on....
任何想法如何轻松实现? 感谢
答案 0 :(得分:3)
如果你只想要配对:
from operator import itemgetter as it
from itertools import repeat
n = 3
# sort_values = order pandas < 0.17
new_d = (zip(repeat(row["index"]), map(it(0),(row[1:].sort_values(ascending=0)[:n].iteritems())))
for _, row in df.iterrows())
for row in new_d:
print(list(row))
输出:
[('B', 'option3'), ('B', 'option4'), ('B', 'option1')]
[('C', 'option2'), ('C', 'option5'), ('C', 'option1')]
[('D', 'option5'), ('D', 'option1'), ('D', 'option2')]
[('E', 'option1'), ('E', 'option2'), ('E', 'option3')]
[('F', 'option3'), ('F', 'option1'), ('F', 'option2')]
这也维持了秩序。
如果您需要列表清单:
from operator import itemgetter as it
from itertools import repeat
n = 3
new_d = [list(zip(repeat(row["index"]), map(it(0),(row[1:].sort_values(ascending=0)[:n].iteritems()))))
for _, row in df.iterrows()]
输出:
[[('A', 'option3'), ('A', 'option2'), ('A', 'option4')],
[('B', 'option3'), ('B', 'option4'), ('B', 'option1')],
[('C', 'option2'), ('C', 'option5'), ('C', 'option1')],
[('D', 'option5'), ('D', 'option1'), ('D', 'option2')],
[('E', 'option1'), ('E', 'option2'), ('E', 'option3')],
[('F', 'option3'), ('F', 'option1'), ('F', 'option2')]]
或者使用pythons sorted:
new_d = [list(zip(repeat(row["index"]), map(it(0), sorted(row[1:].iteritems(), key=it(1) ,reverse=1)[:n])))
for _, row in df.iterrows()]
实际上这是最快的,如果你真的想要字符串,那么根据你的需要格式化输出是非常简单的。
答案 1 :(得分:2)
我们假设
N = 3
首先,我将创建输入字段矩阵,并为每个字段记住此单元格的原始选项:
matrix = [[(j, 'option' + str(i)) for j in df['option' + str(i)]] for i in range(1,6)]
这一行的结果将是:
[
[(1, 'option1'), (5, 'option1'), (3, 'option1'), (7, 'option1'), (9, 'option1'), (3, 'option1')],
[(8, 'option2'), (4, 'option2'), (5, 'option2'), (6, 'option2'), (9, 'option2'), (2, 'option2')],
[(9, 'option3'), (9, 'option3'), (1, 'option3'), (3, 'option3'), (9, 'option3'), (5, 'option3')],
[(3, 'option4'), (8, 'option4'), (3, 'option4'), (5, 'option4'), (7, 'option4'), (0, 'option4')],
[(2, 'option5'), (3, 'option5'), (4, 'option5'), (9, 'option5'), (4, 'option5'), (2, 'option5')]
]
然后我们可以使用zip函数轻松转换矩阵,按元组的第一个元素对结果行进行排序,并取N个第一项:
transformed = [sorted(l, key=lambda x: x[0], reverse=True)[:N] for l in zip(*matrix)]
转换后的列表将如下所示:
[
[(9, 'option3'), (8, 'option2'), (3, 'option4')],
[(9, 'option3'), (8, 'option4'), (5, 'option1')],
[(5, 'option2'), (4, 'option5'), (3, 'option1')],
[(9, 'option5'), (7, 'option1'), (6, 'option2')],
[(9, 'option1'), (9, 'option2'), (9, 'option3')],
[(5, 'option3'), (3, 'option1'), (2, 'option2')]
]
最后一步是通过以下方式加入列索引和结果元组:
for id, top in zip(df['index'], transformed):
for option in top:
print id + ',' + option[1]
print ''
答案 2 :(得分:1)
dfc = df.copy()
result = {}
#First, I would effectively transpose this
for key in dfc:
if key != 'index':
for i in xrange(0,len(dfc['index'])):
if dfc['index'][i] not in result:
result[dfc['index'][i]] = []
result[dfc['index'][i]] += [(key,dfc[key][i])]
def get_topn(result,n):
#Use this to get the top value for each option
return [x[0] for x in sorted(result,key=lambda x:-x[1])[0:min(len(result),n)]]
#Lastly, print the output in your desired format.
n = 3
keys = sorted([k for k in result])
for key in keys:
for option in get_topn(result[key],n):
print str(key) + ',' + str(option)
print
答案 3 :(得分:0)
这可能不是那么优雅,但我认为它几乎可以得到你想要的东西:
n = 3
df.index = pd.Index(df['index'])
del df['index']
df = df.transpose().unstack()
for i, g in df.groupby(level=0):
g = g.sort_values(ascending=False)
print i, list(g.index.get_level_values(1)[:n])
答案 4 :(得分:0)
另一个疯狂的单行,给定n = 3
{index:option for (index, option) in zip(df['index'],
[df.columns[pd.notnull(x[1].where(x[1][1:].sort_values()[-n:]))].tolist()
for x in df.iterrows()])}
{'A': ['option2', 'option3', 'option4'],
'C': ['option2', 'option4', 'option5'],
'B': ['option1', 'option3', 'option4'],
'E': ['option1', 'option2', 'option3'],
'D': ['option1', 'option2', 'option5'],
'F': ['option1', 'option3', 'option5']}