首页 > 解决方案 > 将多个值拆分为新行

问题描述

我有一个数据框,其中几列可能在单个观察中具有多个值。这些行中的每个观察在观察的末尾都有一个“/”,无论是否有多个。这意味着一些值看起来像这样:'OneThing/' 而另一些像这样:'OneThing/AnotherThing/'

我需要在观察中获取多个值的值并将它们拆分为单独的行。

这是数据框之前的一般示例:

ID  Date   Name ColA   ColB   Col_of_Int                        ColC   ColD
1   09/12  Ann  String String OneThing/                         String String
2   09/13  Pete String String OneThing/AnotherThing             String String
3   09/13  Ann  String String OneThing/AnotherThing/ThirdThing/ String String
4   09/12  Pete String String OneThing/                         String String

我想要的输出是:

ID  Date   Name ColA   ColB   Col_of_Int                        ColC   ColD
1   09/12  Ann  String String OneThing                         String String
2   09/13  Pete String String OneThing                         String String
2   09/13  Pete String String Another Thing                    String String
3   09/13  Ann  String String OneThing                         String String
3   09/13  Ann  String String AnotherThing                     String String
3   09/13  Ann  String String ThirdThing                       String String
4   09/12  Pete String String OneThing/                        String String

我尝试了以下方法:

df = df[df['Column1'].str.contains('/')]
df_split = df[df['Column1'].str.contains('/')]
df1 = df_split.copy()
df2 = df_split.copy()

split_cols = ['Column1']

for c in split_cols:
    df1[c] = df1[c].apply(lambda x: x.split('/')[0])
    df2[c] = df2[c].apply(lambda x: x.split('/')[1])

new_rows = df1.append(df2)
df.drop(df_split.index, inplace=True)
df = df.append(new_rows, ignore_index=True)

这可行,但我认为它在每个“/”之后创建新行,这意味着为每个观察创建一个新行,只有一个值(我想要零个新行),并且正在创建两个新行每个观察值都有两个值(只需要一个),等等。

当观察中有三个或更多值时,这尤其令人沮丧,因为我得到了几个不必要的行。

有什么办法可以解决这个问题,以便只有一个以上的观察被添加到新行中?

标签: pythonpython-3.xpandassplitappend

解决方案


如果您使用df['column_of_interest'] = df['column_of_interest'].str.rstrip('/'),您的方法会起作用(我认为),因为它会/在您的观察结束时消除这种烦人的情况。但是,循环是无效的,并且您拥有它的方式要求您知道在您的列中最多有多少观察值。这是另一种方式,我认为可以满足您的需求:

举个例子df

df = pd.DataFrame({'column_of_interest':['onething/', 
                                         'onething/twothings/', 
                                         'onething/twothings/threethings/'], 
                   'values1': [1,2,3], 
                   'values2': [5,6,7]})

>>> df
                column_of_interest  values1  values2
0                        onething/        1        5
1              onething/twothings/        2        6
2  onething/twothings/threethings/        3        7

这有点混乱,因为您想大概保留列中的数据之外column_of_interest。因此,您可以使用以下方法临时找到它们并将它们放在一边:

value_columns = [i for i in df.columns if i != 'column_of_interest']

并将它们放入索引中以进行以下操作(最后恢复它们):

new_df = (df.set_index(value_columns)
          .column_of_interest.str.rstrip('/')
          .str.split('/')
          .apply(pd.Series)
          .stack()
          .rename('new_column_of_interest')
          .reset_index(value_columns))

你的new_dfthen 看起来像:

>>> new_df
   values1  values2 new_column_of_interest
0        1        5               onething
0        2        6               onething
1        2        6              twothings
0        3        7               onething
1        3        7              twothings
2        3        7            threethings

或者,使用merge

new_df = (df[value_columns].merge(df.column_of_interest
                        .str.rstrip('/')
                        .str.split('/')
                        .apply(pd.Series)
                        .stack()
                        .reset_index(1, drop=True)
                        .to_frame('new_column_of_interest'),
                        left_index=True, right_index=True))

编辑:在您发布的数据框上,这会导致:

   ID   Date  Name    ColA    ColB    ColC    ColD new_column_of_interest
0   1  09/12   Ann  String  String  String  String               OneThing
0   2  09/13  Pete  String  String  String  String               OneThing
1   2  09/13  Pete  String  String  String  String           AnotherThing
0   3  09/13   Ann  String  String  String  String               OneThing
1   3  09/13   Ann  String  String  String  String           AnotherThing
2   3  09/13   Ann  String  String  String  String             ThirdThing
0   4  09/12  Pete  String  String  String  String               OneThing

推荐阅读