【发布时间】:2020-07-22 22:34:02
【问题描述】:
我有一个宽格式的数据框:
import pandas as pd
df = pd.DataFrame({'time': [1, 2, 3],
'factor': ['a','a','b'],
'variable1': [0,0,0],
'variable2': [0,0,1],
'variable3': [0,2,0],
'variable4': [2,0,1],
'variable5': [1,0,1],
'variable6': [0,1,1],
'O1V1': [0,0.2,-0.3],
'O1V2': [0,0.4,-0.9],
'O1V3': [0.5,0.2,-0.6],
'O1V4': [0.5,0.2,-0.6],
'O1V5': [0,0.2,-0.3],
'O1V6': [0,0.4,-0.9],
'O1V7': [0.5,0.2,-0.6],
'O1V8': [0.5,0.2,-0.6],
'O2V1': [0,0.5,0.3],
'O2V2': [0,0.2,0.9],
'O2V3': [0.6,0.1,-0.3],
'O2V4': [0.5,0.2,-0.6],
'O2V5': [0,0.5,0.3],
'O2V6': [0,0.2,0.9],
'O2V7': [0.6,0.1,-0.3],
'O2V8': [0.5,0.2,-0.6],
'O3V1': [0,0.7,0.4],
'O3V2': [0.9,0.2,-0.3],
'O3V3': [0.5,0.2,-0.7],
'O3V4': [0.5,0.2,-0.6],
'O3V5': [0,0.7,0.4],
'O3V6': [0.9,0.2,-0.3],
'O3V7': [0.5,0.2,-0.7],
'O3V8': [0.5,0.2,-0.6]})
数据框的每一行代表一个时间段。有多个“对象”被监测,即 O1、O2 和 O3。每个受试者有 8 个变量被测量。我需要将此数据转换为长格式,其中每一行包含一个主题在给定时间段的信息,但只有前 4 个主题变量,以及第 2-4 列中有关此时间段的额外信息,但是不是第 5-8 列。
最终输出应如下所示:
df_final = pd.DataFrame({'time': [1, 2, 3, 1, 2, 3, 1, 2, 3],
'factor': ['a','a','b','a','a','b','a','a','b'],
'variable1': [0,0,0,0,0,0,0,0,0],
'variable2': [0,0,1,0,0,1,0,0,1],
'id': [1,1,1,2,2,2,3,3,3],
'V1': [0,0.2,-0.3,0,0.5,0.3,0,0.7,0.4],
'V2': [0,0.4,-0.9,0,0.2,0.9,0.9,0.2,-0.3],
'V3': [0.5,0.2,-0.6,0.6,0.1,-0.3,0.5,0.2,-0.7],
'V4': [0.5,0.2,-0.6,0.5,0.2,-0.6,0.5,0.2,-0.6]})
我可以使用如下的 for 循环来实现这一点(此代码按时间而不是 id 对数据进行排序,但按 id 排序不是必需的):
import numpy as np
#make every 8 columns of first row into its own row
long = np.array(df.iloc[0,:]).reshape(-1,8)
#make array of numbers 1-3 (I'm not an experienced python programmer,
#so I suspect that this is a very verbose way of achieving this)
array = np.arange(3)
array = array.reshape(3,1)
array+=1
#concatenate first 4 columns of first row with first four columns of every other row, adding index from array variable
long = np.concatenate([np.tile(long[0,:4].reshape(-1,4),(3,1)),array,long[1:,:4]],axis=1)
#repeat this process for each object id and concatenate
for i in [1,2]:
temp = np.array(df.iloc[i,:]).reshape(-1,8)
temp = np.concatenate([np.tile(temp[0,:4].reshape(-1,4),(3,1)),array,temp[1:,:4]],axis=1)
long = np.concatenate([long,temp])
这个方法达到了预期的效果,但是我有问题:
-
此方法依赖于在主题变量出现之前有 8 个变量的事实,从而允许 .reshape (-1,8) 行起作用。我正在尝试找到一种不管非主题变量的数量如何都可以工作的方法。
-
这个解决方案中的 for 循环似乎是可以避免的。我曾尝试寻找利用 NumPy 函数来实现此目的的方法,但没有找到任何方法,或者至少不明白如何像这样使用它们。我知道我可以编写自己的函数并将其应用于每一行,但是我特别希望了解如何使用典型的 Python 包,因为我是 Python 新手。
【问题讨论】:
标签: python pandas numpy formatting