Pandas 将不同长度的列表分解成行
Posted
技术标签:
【中文标题】Pandas 将不同长度的列表分解成行【英文标题】:Pandas Explode lists with different lengths, into rows 【发布时间】:2018-02-03 17:23:57 【问题描述】:我有一个 pandas 数据框,其中一列包含不同长度的列表。 pandas中展开列表的解决方案都是假设要展开的列表长度都是一样的。
这是我的 df:
Dep Exp Fl-No Shared Codes
0 20:58 20:55 LX 736 [No shared codes]
1 21:23 20:55 LX 818 [Dummy, LH 5809]
2 21:27 21:00 JU 375 [No shared codes]
4 21:28 21:00 LX 770 [Dummy, SN 5102]
7 21:31 21:10 LX 1842 [Dummy, LH 5880, TP 8184, A3 1985]
这就是我要找的:
Dep Exp Fl-No Shared Codes
0 20:58 20:55 LX 736 No shared codes
1 21:23 20:55 LX 818 Dummy
1 21:23 20:55 LX 818 LH 5809
2 21:27 21:00 JU 375 No shared codes
4 21:28 21:00 LX 770 Dummy
4 21:28 21:00 LX 770 SN 5102
7 21:31 21:10 LX 1842 Dummy
7 21:31 21:10 LX 1842 LH 5880
7 21:31 21:10 LX 1842 TP 8184
7 21:31 21:10 LX 1842 A3 1985
有人有什么建议吗?
【问题讨论】:
@Wen 我不认为 OP 可以在这里使用wide_to_long
。数据格式不正确。
@Wen 其实我错了。我找到了一种使用wide_to_long的方法,但它太糟糕了,不值得放。
@cᴏʟᴅsᴘᴇᴇᴅ PiR 的回答怎么样?
@Wen 我投了赞成票。为什么?
@cᴏʟᴅsᴘᴇᴇᴅ 多次看到此类问题..我真的希望熊猫可以记录其中一个解决方案并将其命名为unlistify
【参考方案1】:
与@coldspeed 非常相似。我采取了几个不同的步骤。
s = df['Shared Codes']
i = np.arange(len(df)).repeat(s.str.len())
df.iloc[i, :-1].assign(**'Shared Codes': np.concatenate(s.values))
Dep Exp Fl-No Shared Codes
0 20:58 20:55 LX 736 No shared codes
1 21:23 20:55 LX 818 Dummy
1 21:23 20:55 LX 818 LH 5809
2 21:27 21:00 JU 375 No shared codes
4 21:28 21:00 LX 770 Dummy
4 21:28 21:00 LX 770 SN 5102
7 21:31 21:10 LX 1842 Dummy
7 21:31 21:10 LX 1842 LH 5880
7 21:31 21:10 LX 1842 TP 8184
7 21:31 21:10 LX 1842 A3 1985
【讨论】:
看来np.repeat
无论你选择走哪条路都是必须的。这是我得到它时感觉非常好的几个解决方案之一。【参考方案2】:
使用np.repeat
和np.hstack
的一种可能性:
print(df)
Dep Exp Fl-No Shared Codes
0 20:58 20:55 LX 736 [No shared codes]
1 21:23 20:55 LX 818 [Dummy, LH 5809]
2 21:27 21:00 JU 375 [No shared codes]
4 21:28 21:00 LX 770 [Dummy, SN 5102]
7 21:31 21:10 LX 1842 [Dummy, LH 5880, TP 8184, A3 1985]
x = df.iloc[:, :-1].values.repeat(df['Shared Codes'].apply(len), 0)
y = df['Shared Codes'].apply(pd.Series).stack().values.reshape(-1, 1)
out = pd.DataFrame(np.hstack((x, y)), columns=df.columns)
print(out)
Dep Exp Fl-No Shared Codes
0 20:58 20:55 LX 736 No shared codes
1 21:23 20:55 LX 818 Dummy
2 21:23 20:55 LX 818 LH 5809
3 21:27 21:00 JU 375 No shared codes
4 21:28 21:00 LX 770 Dummy
5 21:28 21:00 LX 770 SN 5102
6 21:31 21:10 LX 1842 Dummy
7 21:31 21:10 LX 1842 LH 5880
8 21:31 21:10 LX 1842 TP 8184
9 21:31 21:10 LX 1842 A3 1985
【讨论】:
@cᴏʟᴅsᴘᴇᴇᴅdf.set_index(['Dep','Exp','Fl-No'])['Shared Codes'].apply(pd.Series).stack().reset_index().drop('level_3',1)
另一个类似的问题链接***.com/questions/45871154/…
@cᴏʟᴅsᴘᴇᴇᴅ 已发布 ~ :)
@BarJacks 还为时不晚。请接受答案。【参考方案3】:
好的,我会再次发布以获取更多信息和其他天才解决方案,请查看link1和link2
df.set_index(['Dep','Exp','Fl-No'])['Shared Codes'].apply(pd.Series).stack().reset_index().drop('level_3',1)
Dep Exp Fl-No Shared Codes
0 20:58 20:55 LX 736 No shared codes
1 21:23 20:55 LX 818 Dummy
2 21:23 20:55 LX 818 LH 5809
3 21:27 21:00 JU 375 No shared codes
4 21:28 21:00 LX 770 Dummy
5 21:28 21:00 LX 770 SN 5102
6 21:31 21:10 LX 1842 Dummy
7 21:31 21:10 LX 1842 LH 5880
8 21:31 21:10 LX 1842 TP 8184
9 21:31 21:10 LX 1842 A3 1985
还有,用pd.wide_to_long
不过,个人不推荐导致矫枉过正。
df1=df['Shared Codes'].apply(pd.Series)
df1.columns='sur'+df1.columns.astype(str)
df=pd.concat([df,df1],axis=1)
pd.wide_to_long(df,['sur'],['Dep','Exp','Fl-No'],'lol').reset_index().drop(['lol','Shared Codes'],axis=1).dropna()
Dep Exp Fl-No Shared Codes
0 20:58 20:55 LX 736 No shared codes
1 21:23 20:55 LX 818 Dummy
2 21:23 20:55 LX 818 LH 5809
3 21:27 21:00 JU 375 No shared codes
4 21:28 21:00 LX 770 Dummy
5 21:28 21:00 LX 770 SN 5102
6 21:31 21:10 LX 1842 Dummy
7 21:31 21:10 LX 1842 LH 5880
8 21:31 21:10 LX 1842 TP 8184
9 21:31 21:10 LX 1842 A3 1985
【讨论】:
【参考方案4】:熊猫 >=0.25
df:
Name Data
0 Bar [Product, Item, X]
1 Foo [Product, Misc]
使用 Explode:
df = df.explode('Data')
df:
Name Data
0 Bar Product
0 Bar Item
0 Bar X
1 Foo Product
1 Foo Misc
【讨论】:
以上是关于Pandas 将不同长度的列表分解成行的主要内容,如果未能解决你的问题,请参考以下文章
Pandas使用split函数基于指定分隔符拆分数据列的内容为列表设置expand参数将拆分结果列表内容转化为多列dataframe(不设置参数n则列表长度不同较短的列表会出现缺失值)
合并两个不同长度的python pandas数据帧,但将所有行保留在输出数据帧中