对于Stack Overflow上的第一个问题,我已经得到了我希望是一个独特/有趣的问题!
我有关于技能评估的数据,目前在一个非常大的熊猫数据框中。每行代表一名学生,每列包含他们对特定技能评估的分数。总共有大约200个技能评估,每个学生只在这些评估的一小部分中得分(典型的是1-20分,但有些学生有更多)。
示例数据帧结构:
id skill1 skill2 skill3 skill4 skill5 ....
1 10 50 NaN 3 NaN
2 Nan 10 2 70 NaN
3 23 NaN 45 NaN 5
我试图以下列格式将这些数据转换为每个学生的空格分隔字符串,以便我们可以将其导入另一个数据存储区:
skill1:10 skill2:50 skill4:3
skill2:10 skill3:2 skill4:70
(注意没有评估分数的技能如何不被添加到列表中)
我已经创建了一个lambda函数来将所有这些技能值与其列标签结合起来:
skillmerge = lambda row: ' '.join([str(row.index[i])+':'+str(row[i]) for i in range(0,len(row)) if row[i]!=np.nan])
当我创建一个单独的系列(1个学生)进行测试时,lambda函数需要不到一秒的时间来创建所需格式的输出字符串。但是,当我创建一个只有2行的数据帧时(再次出于测试目的),该函数只需几分钟即可完成这两行:
testing_df['combined_skills'] = testing_df.apply(skillmerge, axis=1)
看到我在这个数据集中有几百万学生,我正在寻找方法让这个过程可靠地更快地运作。关于我可以解决这个问题的任何想法?
提前感谢您帮助解决我的第一个问题! :d
答案 0 :(得分:1)
使用to_json
然后修复
def to_str(x):
return x.dropna().to_json(double_precision=0) \
.replace('"', '').replace(',', ' ').strip("{}")
df.T.apply(to_str)
或使用列表理解和join
def to_str(x):
return " ".join(["{}:{}".format(k, int(v)) for k, v in x.dropna().iteritems()])
df.T.apply(to_str)
两者都给予
id
1 skill1:10 skill2:50 skill4:3
2 skill2:10 skill3:2 skill4:70
3 skill1:23 skill3:45 skill5:5
dtype: object
让您的解决方案有效
skillmerge = lambda row: ' '.join([str(row.index[i])+':'+str(row[i]) for i in range(len(row)) if not np.isnan(row[i])])
df.T.apply(skillmerge)
请注意np.nan == np.nan
评估为False
。为了测试np.nan
使用np.isnan
或pd.isnull
或pd.notnull
。这个事实让你失去了解决方案。我将其替换为not np.isnan
并且有效。
我借机做了我做的事,因为我更喜欢它。
答案 1 :(得分:0)
试试这个:
ld = df.set_index('id').fillna("").to_dict(orient='records')
ll = [' '.join([ k +":"+ str(v) for k,v in x.iteritems() if v != "" ]) for x in ld ]
ll
['skill2:50.0 skill1:10.0 skill4:3.0',
'skill3:2.0 skill2:10.0 skill4:70.0',
'skill3:45.0 skill1:23.0 skill5:5.0']