我有一个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
非常感谢任何帮助。
答案 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
Series
到df1
:
df1 = pd.concat([s1,s2], axis=1, keys=['value','date'])
删除旧列value
和date
以及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
拆分value
和date
列:
df.value = df.value.str.split(',')
df.date = df.date.str.split(',')
df
现在我们可以在一列或两者上爆炸,一个接一个地爆炸。
explode(df, ['value','date'])
我从@ 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行示例
中200行样本
大型2,000,000行样本
答案 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)
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会改变。我希望有人能帮助我找到解决方案。