在pandas datafram中将多个列拆分为行

2024-05-23 18:30:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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

非常感谢您的帮助。


Tags: 数据pandasdfdatevalueaccountaaticker
3条回答

您可以首先^{}列,通过^{}创建Series,通过^{}删除空白:

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)

然后^{}两者都Seriesdf1

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

删除旧列valuedate^{}

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

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

所以我写了一个函数。

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 = 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在逗号后面的字符串中有空格。我的目标是提供一种通用的方法来分解一个列,因为它已经包含了iterables,我想我已经完成了。

代码

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

两行小样本

enter image description here

中等200行样本

enter image description here

200万行大样本

enter image description here

我根据前面的答案编写了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|
+-----------+------+-----+--------+

相关问题 更多 >