我有一个看起来像这样的DF。
name id apps
john 1 [[app1, v1], [app2, v2], [app3,v3]]
smith 2 [[app1, v1], [app4, v4]]
我想扩展“应用程序”列,使其看起来像这样。
name id app_name app_version
john 1 app1 v1
john 1 app2 v2
john 1 app3 v3
smith 2 app1 v1
smith 2 app4 v4
感谢您的帮助
答案 0 :(得分:4)
您可以两次var p = Point(x:0,y:0)
p = Point(x:p.x+1,y:p.y)
来获得所需的中间步骤,然后再合并回原始数据框。
.apply(pd.Series)
答案 1 :(得分:3)
您始终可以拥有蛮力解决方案。像这样:
name, id, app_name, app_version = [], [], [], []
for i in range(len(df)):
for v in df.loc[i,'apps']:
app_name.append(v[0])
app_version.append(v[1])
name.append(df.loc[i, 'name'])
id.append(df.loc[i, 'id'])
df = pd.DataFrame({'name': name, 'id': id, 'app_name': app_name, 'app_version': app_version})
将完成工作。
请注意,如果df ['apps']是字符串,我假设df ['apps']是字符串列表,那么您需要:eval(df.loc[i,'apps'])
而不是df.loc[i,'apps']
答案 2 :(得分:3)
另一种方法是(也应该相当快):
#Repeat the columns without the list by the str length of the list
m=df.drop('apps',1).loc[df.index.repeat(df.apps.str.len())].reset_index(drop=True)
#creating a df exploding the list to 2 columns
n=pd.DataFrame(np.concatenate(df.apps.values),columns=['app_name','app_version'])
#concat them together
df_new=pd.concat([m,n],axis=1)
name id app_name app_version
0 john 1 app1 v1
1 john 1 app2 v2
2 john 1 app3 v3
3 smith 2 app1 v1
4 smith 2 app4 v4
答案 3 :(得分:3)
pd.Series
的链很容易理解,如果您想了解更多方法,请检查unnesting
df.set_index(['name','id']).apps.apply(pd.Series).\
stack().apply(pd.Series).\
reset_index(level=[0,1]).\
rename(columns={0:'app_name',1:'app_version'})
Out[541]:
name id app_name app_version
0 john 1 app1 v1
1 john 1 app2 v2
2 john 1 app3 v3
0 smith 2 app1 v1
1 smith 2 app4 v4
方法二稍微修改我写的功能
def unnesting(df, explode):
idx = df.index.repeat(df[explode[0]].str.len())
df1 = pd.concat([
pd.DataFrame({x: sum(df[x].tolist(),[])}) for x in explode], axis=1)
df1.index = idx
return df1.join(df.drop(explode, 1), how='left')
然后
yourdf=unnesting(df,['apps'])
yourdf['app_name'],yourdf['app_version']=yourdf.apps.str[0],yourdf.apps.str[1]
yourdf
Out[548]:
apps id name app_name app_version
0 [app1, v1] 1 john app1 v1
0 [app2, v2] 1 john app2 v2
0 [app3, v3] 1 john app3 v3
1 [app1, v1] 2 smith app1 v1
1 [app4, v4] 2 smith app4 v4
或
yourdf=unnesting(df,['apps']).reindex(columns=df.columns.tolist()+['app_name','app_version'])
yourdf[['app_name','app_version']]=yourdf.apps.tolist()
yourdf
Out[567]:
apps id name app_name app_version
0 [app1, v1] 1 john app1 v1
0 [app2, v2] 1 john app2 v2
0 [app3, v3] 1 john app3 v3
1 [app1, v1] 2 smith app1 v1
1 [app4, v4] 2 smith app4 v4
答案 4 :(得分:1)
我的建议(可能有更简单的方法)是将DataFrame.apply
与pd.concat
一起使用:
def expand_row(row):
return pd.DataFrame({
'name': row['name'], # row.name is the name of the series
'id': row['id'],
'app_name': [app[0] for app in row.apps],
'app_version': [app[1] for app in row.apps]
})
temp_dfs = df.apply(expand_row, axis=1).tolist()
expanded = pd.concat(temp_dfs)
expanded = expanded.reset_index() # put index in the correct order
print(expanded)
# name id app_name app_version
# 0 john 1 app1 v1
# 1 john 1 app2 v2
# 2 john 1 app3 v3
# 3 smith 2 app1 v1
# 4 smith 2 app4 v4
此外,这是仅使用python的解决方案,如果我的直觉是正确的,则应该很快:
rows = df.values.tolist()
expanded = [[row[0], row[1], app[0], app[1]]
for row in rows
for app in row[2]]
df = pd.DataFrame(
expanded, columns=['name', 'id', 'app_name', 'app_version'])
# name id app_name app_version
# 0 john 1 app1 v1
# 1 john 1 app2 v2
# 2 john 1 app3 v3
# 3 smith 2 app1 v1
# 4 smith 2 app4 v4