Pandas动态宽到长基于时间

q9rjltbz  于 2023-01-19  发布在  其他
关注(0)|答案(2)|浏览(87)

我有Pandas Dataframe ,包含以下数据

ID  Q1_rev  Q1_transcnt Q2_rev  Q2_transcnt Q3_rev  Q3_transcnt Q4_rev  Q4_transcnt
1   100        2         200       4         300       6          400     8
2   101        3         201       5         301       7          401     9

Dataframe 如下所示

我想做以下几点
a)对于每个ID,创建3行(来自8个输入列数据)
b)每行应包含两列数据
c)随后的行应该将列移位1(四分之一数据)。
为了更好地理解,我希望我的输出如下所示

我尝试了下面的基础上,所以职位在这里,但无法获得预期的输出

s = 3
n = 2

cols = ['1st_rev','1st_transcnt','2nd_rev','2nd_transcnt']

output = pd.concat((df.iloc[:,0+i*s:6+i*s].set_axis(cols, axis=1) for i in range(int((df.shape[1]-(s*n))/n))), ignore_index=True, axis=0).set_index(np.tile(df.index,2))

能帮我一下吗?问题是实时的,n=2不会是这样的。它也可能是4或5。意思是,我可能有下面的,而不是'1st_rev','1st_transcnt','2nd_rev','2nd_transcnt'。你可以看到有4对列。

'1st_rev','1st_transcnt','2nd_rev','2nd_transcnt','3rd_rev','3rd_transcnt','4th_rev','4th_transcnt'
t98cgbkg

t98cgbkg1#

通过按_拆分列名并按x.split('_')[1]拆分选定的第二个子字符串,使用DataFrame.groupby的自定义函数:

N = 2
df1 = df.set_index('ID')

def f(x,n=N):
    out = np.array([[list(L[x:x+n]) for x in range(len(L)-n+1)] for L in x.to_numpy()])
    return pd.DataFrame(np.vstack(out))
       
df2 = (df1.groupby(lambda x: x.split('_')[1], axis=1, sort=False)
           .apply(f)
           .sort_index(axis=1, level=1, sort_remaining=False))

df2.index = np.repeat(df1.index, int(len(df2.index) / len(df1.index)))
df2.columns = df2.columns.map(lambda x: f'{x[1] + 1}_{x[0]}')
print (df2)
    1_rev  1_transcnt  2_rev  2_transcnt
ID                                      
1     100           2    200           4
1     200           4    300           6
1     300           6    400           8
2     101           3    201           5
2     201           5    301           7
2     301           7    401           9

使用3个窗口进行测试:

N = 3
df1 = df.set_index('ID')

def f(x,n=N):
    out = np.array([[list(L[x:x+n]) for x in range(len(L)-n+1)] for L in x.to_numpy()])
    return pd.DataFrame(np.vstack(out))
       
df2 = (df1.groupby(lambda x: x.split('_')[1], axis=1, sort=False)
           .apply(f)
           .sort_index(axis=1, level=1, sort_remaining=False))

df2.index = np.repeat(df1.index, int(len(df2.index) / len(df1.index)))
df2.columns = df2.columns.map(lambda x: f'{x[1] + 1}_{x[0]}')
print (df2)
    1_rev  1_transcnt  2_rev  2_transcnt  3_rev  3_transcnt
ID                                                         
1     100           2    200           4    300           6
1     200           4    300           6    400           8
2     101           3    201           5    301           7
2     201           5    301           7    401           9
eit6fx6z

eit6fx6z2#

一个选项是for循环或列表解析,后跟连接和排序:

temp = df.set_index('ID')
cols = ['1st_rev','1st_transcnt','2nd_rev','2nd_transcnt']
outcome = [temp
          .iloc(axis=1)[n:n+4]
          .set_axis(cols, axis = 1)
          for n in range(0, len(cols)+2, 2)]
pd.concat(outcome).sort_index()

    1st_rev  1st_transcnt  2nd_rev  2nd_transcnt
ID                                              
1       100             2      200             4
1       200             4      300             6
1       300             6      400             8
2       101             3      201             5
2       201             5      301             7
2       301             7      401             9

为了使它更通用,可以使用while循环(你可以使用for循环-while循环看起来更可读/更容易理解):

def reshape_N(df, N):
    # you can pass your custom column names here instead
    # as long as it matches the width
    # of the dataframe
    columns = ['rev', 'transcnt']
    columns = np.tile(columns, N)
    numbers = np.arange(1, N+1).repeat(2)
    columns = [f"{n}_{ent}" 
               for n, ent 
               in zip(numbers, columns)]
    contents = []
    start = 0
    end = N * 2
    temp = df.set_index("ID")
    while (end < temp.columns.size):
        end += start
        frame = temp.iloc(axis=1)[start:end]
        frame.columns = columns
        contents.append(frame)
        start += 2
    if not contents:
        return df
    return pd.concat(contents).sort_index()

让我们应用这个函数:

reshape_N(df, 2)
    1_rev  1_transcnt  2_rev  2_transcnt
ID                                      
1     100           2    200           4
1     200           4    300           6
1     300           6    400           8
2     101           3    201           5
2     201           5    301           7
2     301           7    401           9

reshape_N(df, 3)
    1_rev  1_transcnt  2_rev  2_transcnt  3_rev  3_transcnt
ID                                                         
1     100           2    200           4    300           6
1     200           4    300           6    400           8
2     101           3    201           5    301           7
2     201           5    301           7    401           9

相关问题