Pandas 在dataframe中将多个列拆分为行

Pandas 在dataframe中将多个列拆分为行,pandas,join,dataframe,split,multiple-columns,Pandas,Join,Dataframe,Split,Multiple Columns,我有一个熊猫数据框,如下所示: ticker account value date aa assets 100,200 20121231, 20131231 bb liabilities 50, 150 20141231, 20131231 我想将df['value']和df['date']分开,使数据框如下所示: ticker account value date a

我有一个熊猫数据框,如下所示:

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
非常感谢您的帮助

您可以通过以下方式首先创建列、创建系列和删除空白:

然后将
系列
df1
连接起来:

df1 = pd.concat([s1,s2], axis=1, keys=['value','date'])
删除旧列
日期
和:


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

所以我写了一个函数来实现它

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)
但在使用它之前,我们需要在列中列出列表(或iterable)

安装程序

拆分
日期
列:

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

df

现在我们可以在任意一列或两列上爆炸,一列接一列

解决方案


时机 我从@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行样本

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'])

中等200行样本

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'])

200万行大样本

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'])

我根据前面的答案编写了
explode
函数。它可能对任何想要快速获取和使用它的人都有用

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)
@piRSquared给出的示例:

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

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

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

@提提帕塔:你的回答非常有效,但我认为你的代码中有一个小“错误”,我自己找不到

我使用这个问题中的示例,只更改了值

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”行中,而不是“2.1”

因此,孔数据集将发生更改。我希望有人能帮我找到解决办法。

Pandas>=0.25
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

我对时间很好奇;)
IterItems
速度很慢,但另一方面有很多操作,如
stack
concat
join
,所以这可能是可以比较的。我看到解决方案的不同之处——我使用
strip
。您是否也可以将其添加到解决方案中,然后再次尝试计时?“我想你会忘记的。”耶斯雷尔说。注意我在下面写的####TimingTank you jezrael和Pirsquare两个答案!!耶斯雷尔,你的方法很有效。重复问题:这能回答你的问题吗?
df.value = df.value.str.split(',')
df.date = df.date.str.split(',')
df = df.explode('value').explode("date").reset_index(drop=True)
    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