3

我有一个这种形状的数据源(csv 文件):

在此处输入图像描述

样本原始数据如下:

id  stage   D1  D2  D3  D4  D5  D6
1   base    A                   
1   s1          2   2   4   5
1   s2          3   3   6   7
2   base    AA                  
2   s1          5   3   4   3
2   s2          3   3   2   4
2   s3          2   2   3   6
3   base    B                   
3   s1          4   4   4   5
4   base    BC                  

第一行是一个 ID,所有具有相同 ID 的行都与同一个实验相关。

当我在 Pandas 中将它读成这个形状时,我需要把它弄平并改变它的形状:

在此处输入图像描述

id  stage   D1  D2  D3_s1   D4_s1   D5_s1   D6_s1   D3_s2   D4_s2   D5_s2   D6_s2   D3_s3   D4_s3   D5_s3   D6_s3
1   base    A       2   2   4   5   3   3   6   7               
2   base    AA      5   3   4   3   3   3   2   4   2   2   3   6
3   base    B       4   4   4   5                               
4   base    BC                                                  

在 Python 中执行此操作的最佳方法是什么?

作为一名 C/C++ 程序员,我开始使用几个循环来遍历每个单元格并创建一个具有所需形状的新数据框(仍然没有成功!)。

我相信应该有更好的方法,而不是遍历所有行和列。

我的问题:

在 Python 中执行此操作的最佳方法是什么?

怎样才能发现D2是空白的,可以丢掉呢?

4

3 回答 3

2

假设您已经将数据读入 DataFrame:

  • 将其拆分为 2 个数据框:(base包含带有 的行stage = base)和other
  • 取消堆叠第二个数据框并更改列名
  • 重新组合两者

编码

is_base = df['stage'] == 'base'
base = df.loc[is_base, 'id':'D2'].set_index('id')
other =  df.loc[~is_base, ['id','stage','D3','D4','D5','D6']].set_index(['id', 'stage'])

other = other.unstack()
other.columns = other.columns.get_level_values(0) + '_' + other.columns.get_level_values(1)

# Reset index if needed
final = pd.merge(base, other, left_index=True, right_index=True)
于 2020-08-11T13:03:57.067 回答
1

作为一名 C++ 程序员,你会很高兴知道出于性能原因,pandas 中的许多核心函数实际上都是用 C++ 编写的

我们可以使用两个过滤器和一个MultiIndex通过unstacking。

s = df1[df1['stage'].ne('base')]


s1 = s.set_index(['id','stage']).stack().unstack([-1,-2])
s1.columns = [f'{x}_{y}' for x,y in s1.columns] 
# to match your output we flatten the multi index.

print(s1)

   D1_s1 D2_s1 D3_s1 D4_s1 D1_s2 D2_s2 D3_s2 D4_s2 D1_s3 D2_s3 D3_s3 D4_s3
id                                                                        
1      2     2     4     5     3     3     6     7   NaN   NaN   NaN   NaN
2      5     3     4     3     3     3     2     4     2     2     3     6
3      4     4     4     5   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN

然后我们过滤base值并根据id列连接。

df2 = df1.loc[df1['stage'].eq('base'), ['id','stage','D1','D2']].set_index('id').join(s1)

至于删除 D2,如果它是空白的,一个简单的if就可以了。

if df2['D2'].isna().all():
    df2 = df2.drop('D2',1)


print(df2)

   stage  D1 D1_s1 D2_s1 D3_s1 D4_s1 D1_s2 D2_s2 D3_s2 D4_s2 D1_s3 D2_s3  \
id                                                                         
1   base   A     2     2     4     5     3     3     6     7   NaN   NaN   
2   base  AA     5     3     4     3     3     3     2     4     2     2   
3   base   B     4     4     4     5   NaN   NaN   NaN   NaN   NaN   NaN   
4   base  BC   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   

   D3_s3 D4_s3  
id              
1    NaN   NaN  
2      3     6  
3    NaN   NaN  
4    NaN   NaN 
于 2020-08-11T13:01:42.850 回答
-1

你应该把它翻过来,numpy array然后把它弄平并重塑它。像这样:

data=pd.read_csv(#Your CSV File Name).values
data=data.flatten()
data.reshape(#Your New Shape)
于 2020-08-11T13:00:29.807 回答