根据熊猫中奇怪的列分布来组织数据



是否有一种在数据帧中对数据进行分段的优雅方式,其中第一行包括数据所有者的名称,第二行包括标题,所有数据都组织在下面?

我有这个:

0   n_1 NaN NaN NaN NaN n_2 NaN NaN NaN NaN ... n_3 NaN NaN NaN NaN n_4 NaN NaN NaN NaN
1   V1  V2  V3  V4  V5  V1  V2  V3  V4  V5  ... V1  V2  V3  V4  V5  V1  V2  V3  V4  V5
2   45  43  30  32  NaN 45  52  47  47  NaN ... 45  57  51  50  NaN 45  51  47  50  NaN
3   50  53  38  38  NaN 50  55  50  41  NaN ... 50  51  48  49  NaN 50  53  52  52  1
4   50  54  37  41  NaN 50  53  49  49  1   ... 50  54  50  47  NaN 50  54  48  41  1
5   50  51  40  39  NaN 50  53  50  48  NaN ... 50  53  50  49  NaN 50  51  49  50  NaN
6   50  53  47  50  NaN 50  50  47  35  NaN ... 50  55  44  34  NaN 50  50  47  47  NaN
7   50  51  47  45  NaN 50  52  48  48  1   ... 50  51  48  46  NaN 50  51  47  50  NaN
8   50  52  50  50  NaN 50  50  47  50  NaN ... 50  51  47  48  NaN NaN NaN NaN NaN NaN
9   NaN NaN NaN NaN NaN 50  54  51  53  NaN ... 50  52  48  51  NaN NaN NaN NaN NaN NaN

我需要订购,这样我就可以用之类的东西来分析它

0   Own V1  V2  V3  V4  V5  
1   n_1 45  43  30  32  NaN 
2   n_1 50  53  38  38  NaN 
3   n_1 50  54  37  41  NaN 
4   n_1 50  51  40  39  NaN 
5   n_1 50  53  47  50  NaN 
6   n_1 50  51  47  45  NaN 
7   n_1 50  52  50  50  NaN 
8   n_2 45  52  47  47  NaN 
9   n_2 50  55  50  41  NaN 
10  n_2 50  53  49  49  1   
11  n_2 50  53  50  48  NaN 
12  n_2 50  50  47  35  NaN 
13  n_2 50  52  48  48  1   
14  n_2 50  50  47  50  NaN 
15  n_2 50  54  51  53  NaN 
16  n_3 45  57  51  50  NaN 
17  n_3 50  51  48  49  NaN 
18  n_3 50  54  50  47  NaN 
19  n_3 50  53  50  49  NaN 
20  n_3 50  55  44  34  NaN 
21  n_3 50  51  48  46  NaN 
22  n_3 50  51  47  48  NaN 
23  n_3 50  52  48  51  NaN
24  n_4 45  51  47  50  NaN
25  n_4 50  53  52  52  1
26  n_4 50  54  48  41  1
27  n_4 50  51  49  50  NaN
28  n_4 50  50  47  47  NaN
29  n_4 50  50  51  47  NaN

我想制作不同的数据帧,但那会浪费资源。有更优雅的方法吗?

谢谢。

就我个人而言,我会使用多索引。

从源头上看,这应该是可行的。这里的操作参数是headers,其中告诉read_csv函数读取需要哪些参数。

df = pd.read_csv('your_file.csv',headers=[0,1])
df = df.stack(0).reset_index(1).rename(columns={0 : 'own'})
print(df)
1  own  V1  V2  V3  V4   V5
2  n_1  45  43  30  32  NaN
2  n_2  45  52  47  47  NaN
2  n_3  45  57  51  50  NaN
2  n_4  45  51  47  50  NaN
3  n_1  50  53  38  38  NaN
3  n_2  50  55  50  41  NaN
3  n_3  50  51  48  49  NaN
3  n_4  50  53  52  52    1
4  n_1  50  54  37  41  NaN
4  n_2  50  53  49  49    1
4  n_3  50  54  50  47  NaN
4  n_4  50  54  48  41    1
5  n_1  50  51  40  39  NaN
5  n_2  50  53  50  48  NaN
5  n_3  50  53  50  49  NaN
5  n_4  50  51  49  50  NaN
6  n_1  50  53  47  50  NaN
6  n_2  50  50  47  35  NaN
6  n_3  50  55  44  34  NaN
6  n_4  50  50  47  47  NaN
7  n_1  50  51  47  45  NaN
7  n_2  50  52  48  48    1
7  n_3  50  51  48  46  NaN
7  n_4  50  51  47  50  NaN
8  n_1  50  52  50  50  NaN
8  n_2  50  50  47  50  NaN
8  n_3  50  51  47  48  NaN
9  n_2  50  54  51  53  NaN
9  n_3  50  52  48  51  NaN

--

如果您的MultiIndex由于源数据而出现格式错误,我们可以通过手动修复来伪造它。

df = pd.read_csv('your_file.csv',headers=None)
s = df.iloc[:2].T.replace('NaN',np.nan).ffill() # you may need to be smart with your replace here. 
df.columns = pd.MultiIndex.from_frame(s)
df1 = df.stack(0).reset_index(1).rename(columns={0 : 'own'}).iloc[2:]

这将产生与上述相同的结果。

所以我找到了一种使用pandas.DataFrame和for循环的直观方法。也许有更好的方法可以做到这一点(更优雅,资源更少(,所以我很想看看这个问题的其他解决方案。

与此同时,这是我的。

我的解决方案分为两步。第一种是用前一行的NA值填充第一行中的NA值。第二种方法是使用for循环,将数据帧连接起来形成新的数据帧。

为了测试这个例子,我制作了这个数据帧:

df = pd.DataFrame([["n_1", np.nan, np.nan, "n_2", np.nan, np.nan, "n_3", np.nan, np.nan],
["V1", "V2", "V3", "V1", "V2", "V3", "V1", "V2", "V3"],
[1, 1, 1, 2, 2, 2, 3, 3, 3], 
[1, 1, 1, 2, 2, 2, 3, 3, 3]])

我用填写了第一行的NA

df.iloc[0, :] = df.fillna(method='ffill', axis=1).iloc[0, :]

最后,我使用for循环遍历每个组,以正确地连接数据帧的每个段。

new_df = pd.DataFrame(columns=["grp", "V1", "V2", "V3"]) # the new df
all_groups = np.unique(df.iloc[0, :]) # groups = "n_1", "n_2", ...
for grp in all_groups:
group_df = df.loc[:, df.iloc[0, :] == grp] # get the part of the df corresponding to groupe `grp`
group_df = group_df.iloc[1:,:] # remove the first row
group_df.columns = group_df.iloc[0,:] # set the column as ["V1", "V2", "V3"]
group_df["grp"] = grp # create new column "grp" with the group name
group_df = group_df.iloc[1:,:] # remove the row containing ["V1", "V2", "V3"]
new_df = pd.concat([new_df, group_df], axis=0) # concatenate the group_df to the new_df

然后最后的df看起来是:

grp     V1  V2  V3
1   n_1     1   1   1
2   n_1     1   1   1
3   n_2     2   2   2
4   n_2     2   2   2
5   n_3     3   3   3
6   n_3     3   3   3

最新更新