将多个列拆分为pandas数据帧中的行

时间:2016-07-29 05:21:17

标签: pandas join dataframe split multiple-columns

我有一个pandas数据帧如下:

ticker    account      value         date
aa       assets       100,200       20121231, 20131231
bb       liabilities  50, 150       20141231, 20131231

我想拆分df['value']df['date'],以便数据框如下所示:

ticker    account      value         date
aa       assets       100           20121231
aa       assets       200           20131231 
bb       liabilities  50            20141231
bb       liabilities  150           20131231

非常感谢任何帮助。

5 个答案:

答案 0 :(得分:8)

您可以先split列,按stack创建Series并按strip删除空格:

s1 = df.value.str.split(',', expand=True).stack().str.strip().reset_index(level=1, drop=True)
s2 = df.date.str.split(',', expand=True).stack().str.strip().reset_index(level=1, drop=True)

然后concat Seriesdf1

df1 = pd.concat([s1,s2], axis=1, keys=['value','date'])

删除旧列valuedate以及join

print (df.drop(['value','date'], axis=1).join(df1).reset_index(drop=True))
  ticker      account value      date
0     aa       assets   100  20121231
1     aa       assets   200  20131231
2     bb  liabilities    50  20141231
3     bb  liabilities   150  20131231

答案 1 :(得分:6)

我经常注意到这个问题。也就是说,如何将具有列表的列拆分为多行?我见过它叫做爆炸。以下是一些链接:

所以我写了一个能做到的功能。

def explode(df, columns):
    idx = np.repeat(df.index, df[columns[0]].str.len())
    a = df.T.reindex_axis(columns).values
    concat = np.concatenate([np.concatenate(a[i]) for i in range(a.shape[0])])
    p = pd.DataFrame(concat.reshape(a.shape[0], -1).T, idx, columns)
    return pd.concat([df.drop(columns, axis=1), p], axis=1).reset_index(drop=True)

但在我们使用之前,我们需要列中的列表(或可迭代的)。

设置

df = pd.DataFrame([['aa', 'assets',      '100,200', '20121231,20131231'],
                   ['bb', 'liabilities', '50,50',   '20141231,20131231']],
                  columns=['ticker', 'account', 'value', 'date'])

df

enter image description here

拆分valuedate列:

df.value = df.value.str.split(',')
df.date = df.date.str.split(',')

df

enter image description here

现在我们可以在一列或两者上爆炸,一个接一个地爆炸。

解决方案

explode(df, ['value','date'])

enter image description here

时序

我从@ jezrael的时间中删除了strip,因为我无法将其有效地添加到我的手中。这是此问题的必要步骤,因为OP在逗号后面的字符串中有空格。我的目标是提供一种通用的方法来爆炸列,因为它已经有了迭代,我想我已经完成了。

<强>码

def get_df(n=1):
    return pd.DataFrame([['aa', 'assets',      '100,200,200', '20121231,20131231,20131231'],
                         ['bb', 'liabilities', '50,50',   '20141231,20131231']] * n,
                        columns=['ticker', 'account', 'value', 'date'])

小2行示例

enter image description here

中200行样本

enter image description here

大型2,000,000行样本

enter image description here

答案 2 :(得分:1)

我根据以前的答案写了def explode(df, cols, split_on=','): """ Explode dataframe on the given column, split on given delimeter """ cols_sep = list(set(df.columns) - set(cols)) df_cols = df[cols_sep] explode_len = df[cols[0]].str.split(split_on).map(len) repeat_list = [] for r, e in zip(df_cols.as_matrix(), explode_len): repeat_list.extend([list(r)]*e) df_repeat = pd.DataFrame(repeat_list, columns=cols_sep) df_explode = pd.concat([df[col].str.split(split_on, expand=True).stack().str.strip().reset_index(drop=True) for col in cols], axis=1) df_explode.columns = cols return pd.concat((df_repeat, df_explode), axis=1) 函数。对于想要快速抓取并使用它的人来说,这可能是有用的。

df = pd.DataFrame([['aa', 'assets', '100,200', '20121231,20131231'],
                   ['bb', 'liabilities', '50,50', '20141231,20131231']],
                  columns=['ticker', 'account', 'value', 'date'])
explode(df, ['value', 'date'])

来自@piRSquared的例子:

+-----------+------+-----+--------+
|    account|ticker|value|    date|
+-----------+------+-----+--------+
|     assets|    aa|  100|20121231|
|     assets|    aa|  200|20131231|
|liabilities|    bb|   50|20141231|
|liabilities|    bb|   50|20131231|
+-----------+------+-----+--------+

<强>输出

<template name="DashboardLayout">
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <div class="col-md-8" style="align-content: right;"><input type="text" name="search" placeholder="Search.."> </div>
        </div>

      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
</template>

答案 3 :(得分:1)

熊猫> = 0.25

df.value = df.value.str.split(',')
df.date = df.date.str.split(',')
df = df.explode('value').explode("date").reset_index(drop=True)

df:

    ticker  account      value  date
0   aa      assets       100    20121231
1   aa      assets       100    20131231
2   aa      assets       200    20121231
3   aa      assets       200    20131231
4   bb      liabilities  50     20141231
5   bb      liabilities  50     20131231
6   bb      liabilities  50     20141231
7   bb      liabilities  50     20131231

答案 4 :(得分:0)

因为我太新了,我不允许写评论,所以我写了一个“答案”。

@titipata你的答案非常好,但在我看来,你的代码中有一个小错误“我无法为自己找到。”

我使用此问题的示例并仅更改了值。

df = pd.DataFrame([['title1', 'publisher1', '1.1,1.2', '1'],
               ['title2', 'publisher2', '2', '2.1,2.2']],
              columns=['titel', 'publisher', 'print', 'electronic'])

explode(df, ['print', 'electronic'])

    publisher   titel   print   electronic
0   publisher1  title1  1.1     1
1   publisher1  title1  1.2     2.1
2   publisher2  title2  2       2.2

如您所见,在'electronic'栏中,行'1'的值应为'1',而不是'2.1'。

因此,孔DataSet会改变。我希望有人能帮助我找到解决方案。