问题描述
pd.DataFrame({'col1':['a','a','b','b'],'col2':[12,2,12,1,13,2.2,14,2.1],'col3':[15,1.5,16,1.7,17,1.1,16.5,1],'col4':[np.nan,np.nan,18,2],})
每行有不同数量的 NaN,有些行有所有 26 列的数据,其他行没有。
我想把它改成这样:
pd.DataFrame({'a1':[12,15,18],'a2':[2,'b1':[12,'b2':[1,2.1,2]})
我希望 a
或 b
的奇数实例为 a1
/b1
,每个偶数实例为 a2
/{{ 1}},然后转换
我认为一个支点会起作用,但不能让它起作用
b2
有什么建议吗?
解决方法
这是我想出的解决方案
设置种子 然后循环并将行附加到原始种子 并创建最终 df
a1=df.iloc[0,1:4]
a2=df.iloc[1,1:4]
b1=df.iloc[2,1:4]
b2=df.iloc[3,1:4]
for i in range(4,df.shape[0]):
if i%4==0: a1=a1.append(df.iloc[i,1:4])
if i%4==1: a2=a2.append(df.iloc[i,1:4])
if i%4==2: b1=b1.append(df.iloc[i,1:4])
if i%4==3: b2=b2.append(df.iloc[i,1:4])
pd.DataFrame({'a1':a1,'a2':a2,'b1':b1,'b2':b2}).reset_index(drop=True)
,
作为类似数据框的完全动态解决方案,但行/列更多/更少,一种方法是使用列表理解concat
转置组,但为此您需要做准备到:
- get
n
- 每个子组的 # 行数 - 将索引更改为将成为列名的内容,为 .T 和 concat 做准备
- 创建单独转置的组
n = int(pd.Series(df[df['col1'] == df['col1'].shift()].index).diff().max())
df.index = pd.concat([pd.Series(cols)]*len(grp.unique()))
grp = (df.groupby('col1').cumcount() // n)
df_new = pd.concat([df[grp == i].T.iloc[1:] for i in range(grp.nunique())],ignore_index=True)
df_new
Out[1]:
a1 b1 a2 b2
0 12 2 12 1
1 15 1.5 16 1.7
2 NaN NaN 17 2
3 13 2.2 14 2.1
4 17 1.1 16.5 1
5 18 2 18 2
,
我建议融化列,去掉不相关的列('变量'),然后创建一个新列,将 col1
与索引的模相结合(得到 0 或 1)。 temp
列生成唯一列,以便可以进行透视。
(
df.melt("col1")
.drop(columns="variable")
.assign(
col1=lambda df: df.col1 + (df.index % 2 + 1).astype(str),temp=lambda df: df.groupby("col1").cumcount(),)
.pivot("temp","col1","value")
.rename_axis(index=None,columns=None)
)
a1 a2 b1 b2
0 12.0 2.0 12.0 1.0
1 13.0 2.2 14.0 2.1
2 15.0 1.5 16.0 1.7
3 17.0 1.1 16.5 1.0
4 NaN NaN 17.0 2.0
5 18.0 2.0 18.0 2.0