是否有一种在数据帧中对数据进行分段的优雅方式,其中第一行包括数据所有者的名称,第二行包括标题,所有数据都组织在下面?
我有这个:
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