【问题标题】:Explode pandas dataframe singe row into multiple rows across multiple columns simultaneously将 pandas 数据帧单行同时分解为跨多列的多行
【发布时间】:2019-06-04 04:35:04
【问题描述】:

我有一个数据框df

df
       col1 act_id col2                                                                                                 
   --------------------
0  40;30;30   act1 A;B;C
1  25;50;25   act2 D;E;F
2     70;30   act3 G;H

我想打破每条记录,使col1col2 列中的值爆炸成多行,但在';' 拆分后col1 中的第一个值对应于第一个值col2';' 上拆分后。所以我的desired_df 应该是这样的:

desired_df
       col1 act_id col2                                                                                                 
       ---------------
    0  40   act1   A
    1  30   act1   B
    2  30   act1   C
    3  25   act2   D
    4  50   act2   E
    5  25   act2   F                                                                                                  
    6  70   act3   G                                                                              
    7  30   act3   H                                                                               

注意:这与Split (explode) pandas dataframe string entry to separate rows 不同,因为这里一条记录的爆炸/拆分不仅仅是跨一列,而是需要将一行拆分或拆分为多行,同时在两列中。

感谢任何帮助。谢谢

【问题讨论】:

标签: python pandas dataframe


【解决方案1】:

一种方法

df2.set_index('act_id').apply(lambda x: pd.Series(x.col1.split(';'),x.col2.split(';')), axis=1).stack().dropna().reset_index()

df2.columns = ['col1','act_id','col2']

  col1 act_id col2
0  A    act1   40 
1  B    act1   30 
2  C    act1   30 
3  D    act2   25 
4  E    act2   50 
5  F    act2   25 
6  G    act3   70 
7  H    act3   30 

【讨论】:

  • 这个解决方案适用于这个特定的 df,虽然当我尝试在大约 1M 行的更大数据帧上运行它时,我得到了 ValueError: cannot reindex from a duplicate axis 的错误,因为即使是更大的原始数据帧只有这些列。
  • 尝试更新..问题可能与重复的索引值有关,如果更新不起作用,请尝试破坏代码并逐步运行它,将帮助您调试问题(发布你在哪一步遇到了错误)
  • 我尝试一步步分解,发现错误出现在set_index('act_id')方法处。我删除了所有其他方法,但仍然得到错误为ValueError: cannot reindex from a duplicate axis 有没有其他方法可以达到预期的结果...?
  • 我仍然遇到错误ValueError: cannot reindex from a duplicate axis
【解决方案2】:

想法是 col1 和 col2 应该被分解,然后在索引上合并并连接回原始数据框。

df1 = df.col1.str.split(";").apply(pd.Series).stack().droplevel(1).reset_index()
df2 = df.col2.str.split(";").apply(pd.Series).stack().droplevel(1).reset_index()
df12 = pd.merge(df1, df2[0], left_index=True, right_index=True)
df12.columns = ["index", "col1", "col2"]

pd.merge(df12, df["act_id"], left_on="index", right_index=True)

【讨论】:

  • AttributeError: 'Series' object has no attribute 'droplevel1'
  • droplevel(1).
【解决方案3】:

通用函数可以是:

list_cols = {'col1','col2'}
other_cols = list(set(df.columns) - set(list_cols))
exploded = [df[col].explode() for col in list_cols]
desired_df = pd.DataFrame(dict(zip(list_cols, exploded)))
desired_df = df[other_cols].merge(desired_df, how="right", left_index=True, right_index=True)

在调用上述函数之前,请先拆分列 1 和列 2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-28
    • 2021-07-23
    • 2021-07-04
    • 1970-01-01
    • 2023-02-05
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    相关资源
    最近更新 更多