Pandas - 合并列并一个接一个地放置?
Pandas - combine columns and put one after another?
我有以下数据框:
a1,a2,b1,b2
1,2,3,4
2,3,4,5
3,4,5,6
理想的输出是:
a,b
1,3
2,4
3,5
2,4
3,5
4,6
dataframe中有很多"a"和"b"命名的headers,最大的是a50和b50。所以我正在寻找将它们全部组合成 "a" 和 "b".
的方法
我认为可以使用 concat,但我不知道如何将它们组合起来,将所有值放在一起。我将不胜感激。
首先我们读取数据帧:
import pandas as pd
from io import StringIO
s = """a1,a2,b1,b2
1,2,3,4
2,3,4,5
3,4,5,6"""
df = pd.read_csv(StringIO(s), sep=',')
然后我们把列堆叠起来,把列数和字母'a'或者'b'分开:
stacked = df.stack().rename("val").reset_index(1).reset_index()
cols_numbers = pd.DataFrame(stacked
.level_1
.str.split('(\d)')
.apply(lambda l: l[:2])
.tolist(),
columns=["col", "num"])
x = cols_numbers.join(stacked[['val', 'index']])
print(x)
col num val index
0 a 1 1 0
1 a 2 2 0
2 b 1 3 0
3 b 2 4 0
4 a 1 2 1
5 a 2 3 1
6 b 1 4 1
7 b 2 5 1
8 a 1 3 2
9 a 2 4 2
10 b 1 5 2
11 b 2 6 2
最后,我们按index
和num
分组得到两列a
和b
,我们填充b
的第一行具有第二个值的列,以获得预期的结果:
result = (x
.set_index("col", append=True)
.groupby(["index", "num"])
.val
.apply(lambda g:
g
.unstack()
.fillna(method="bfill")
.head(1))
.reset_index(-1, drop=True))
print(result)
col a b
index num
0 1 1.0 3.0
2 2.0 4.0
1 1 2.0 4.0
2 3.0 5.0
2 1 3.0 5.0
2 4.0 6.0
最后去掉多索引:result.reset_index(drop=True)
您可以使用 pd.wide_to_long
:
pd.wide_to_long(df.reset_index(), ['a','b'], 'index', 'No').reset_index()[['a','b']]
输出:
a b
0 1 3
1 2 4
2 3 5
3 2 4
4 3 5
5 4 6
我有以下数据框:
a1,a2,b1,b2
1,2,3,4
2,3,4,5
3,4,5,6
理想的输出是:
a,b
1,3
2,4
3,5
2,4
3,5
4,6
dataframe中有很多"a"和"b"命名的headers,最大的是a50和b50。所以我正在寻找将它们全部组合成 "a" 和 "b".
的方法我认为可以使用 concat,但我不知道如何将它们组合起来,将所有值放在一起。我将不胜感激。
首先我们读取数据帧:
import pandas as pd
from io import StringIO
s = """a1,a2,b1,b2
1,2,3,4
2,3,4,5
3,4,5,6"""
df = pd.read_csv(StringIO(s), sep=',')
然后我们把列堆叠起来,把列数和字母'a'或者'b'分开:
stacked = df.stack().rename("val").reset_index(1).reset_index()
cols_numbers = pd.DataFrame(stacked
.level_1
.str.split('(\d)')
.apply(lambda l: l[:2])
.tolist(),
columns=["col", "num"])
x = cols_numbers.join(stacked[['val', 'index']])
print(x)
col num val index
0 a 1 1 0
1 a 2 2 0
2 b 1 3 0
3 b 2 4 0
4 a 1 2 1
5 a 2 3 1
6 b 1 4 1
7 b 2 5 1
8 a 1 3 2
9 a 2 4 2
10 b 1 5 2
11 b 2 6 2
最后,我们按index
和num
分组得到两列a
和b
,我们填充b
的第一行具有第二个值的列,以获得预期的结果:
result = (x
.set_index("col", append=True)
.groupby(["index", "num"])
.val
.apply(lambda g:
g
.unstack()
.fillna(method="bfill")
.head(1))
.reset_index(-1, drop=True))
print(result)
col a b
index num
0 1 1.0 3.0
2 2.0 4.0
1 1 2.0 4.0
2 3.0 5.0
2 1 3.0 5.0
2 4.0 6.0
最后去掉多索引:result.reset_index(drop=True)
您可以使用 pd.wide_to_long
:
pd.wide_to_long(df.reset_index(), ['a','b'], 'index', 'No').reset_index()[['a','b']]
输出:
a b
0 1 3
1 2 4
2 3 5
3 2 4
4 3 5
5 4 6