如何转置和转换此表格:
收货日期 | 金额 | 儿童1 |
衬衫尺码 | 年龄 | 儿童2 |
衬衫尺码 | 年龄 | 儿童3 |
衬衫尺码 | 年龄 |
---|---|---|---|---|---|---|---|---|---|---|
2023 年 5 月 1 日 | 39.00 美元 | 约翰 | S | 11-12 | 玛丽 | L | 14 | 彼得 | S | 9 |
2023 年 5 月 5 日 | (失踪) | 莉莉 | M | 14 | ||||||
(还没有收据) | $38.00 | 特雷西 | L | 8 ½ | 比尔 | M | 13 | 吉尔 | M | 11 |
2023 年 2 月 17 日星期五 | ₿0.00045 | 迈克尔 | S | 10 | ||||||
2023 年 5 月 8 日 | 15.00 美元 | 特里 | L | 15 |
...进入所需的堆叠输出?
收货日期 | 金额 | 标签 |
孩子 |
衬衫尺码 | 年龄 |
---|---|---|---|---|---|
2023 年 5 月 1 日 | $39.00 | 儿童1 | 约翰 | S | 11-12 |
2023 年 5 月 1 日 | $39.00 | 孩子2 | 玛丽 | L | 14 |
2023 年 5 月 1 日 | $39.00 | 儿童3 | 彼得 | S | 9 |
2023 年 5 月 5 日 | (失踪) | 儿童1 | 莉莉 | M | 14 |
(还没有收据) | $38.00 | 儿童1 | 特雷西 | L | 8 ½ |
(还没有收据) | $38.00 | 孩子2 | 比尔 | M | 13 |
(还没有收据) | $38.00 | 儿童3 | 吉尔 | M | 11 |
2023 年 2 月 17 日星期五 | ₿0.00045 | 儿童1 | 迈克尔 | S | 10 |
2023 年 5 月 8 日 | 15.00 美元 | 儿童1 | 特里 | L | 15 |
请注意,源数据列
C2:K
以三个为一组,并且我需要标签 Child 1
、Child 2
和 Child 3
出现在结果中。
现有问题,例如如何在 Google Sheets 中创建“反向透视”仅处理所有未透视列都被同等对待的源数据。这不适用于上面的数据,因为它的列应该以三个为一组进行管理,并且每组三个值应该一起取消透视。
此外,反向枢轴问题的许多答案都使用文本字符串操作和
split()
,这不适用于我的数据,因为它可能会滥用某些格式的日期、布尔值和数字,以及看起来像这些类型的文本字符串。例如,split()
会将上述数据中的文本字符串 11-12
强制转换为数字日期 12 十一月 2023。对于 1 2
、1 2 3
和 1111-2-3
等文本字符串也会发生同样的情况。相反,自定义数字格式(如 ₿0.00045
和 Feb 17 Friday 2023
)的数字和日期会被强制转换为文本字符串。
一些现有答案使用
query()
堆叠数据,但该函数每列仅接受一种数据类型。如果列包含文本和数字的混合,或者偶尔包含日期或布尔值,则多数类型将占主导地位,其他类型将作为空值返回。如果用 query()
处理,上面的数据会丢失几个值。
有一些答案可以通过使用自定义函数来避免上述陷阱,但是自定义函数会遇到“Google表格自定义函数卡在加载中”问题,并且在使用
importrange()
读取电子表格时无法正常工作
或通过 文件 > 共享 > 发布到网络发布。
我有几个像上面这样的数据表,它们都有不同大小的列组和不同数量的固定列。最佳解决方案将很容易配置,而无需修改公式逻辑。
如何使用不使用自定义函数的易于配置的公式反转数据透视并将上面的数据转换为所需的格式而不使其被破坏?
要取消透视列
A1:K
中的数据,其中左侧有 2
固定列,后跟 Label
列和一组 3
未透视列,请使用以下模式:
=let(
data, A1:K,
numColsToRepeat, 2,
numColsPerGroup, 3,
subRows_, lambda(t, o, h, chooserows(t, sequence(h, 1, o))),
subCols_, lambda(t, o, w, choosecols(t, sequence(1, w, o))),
subTable_, lambda(
rowIndex, colIndex, height, width,
subRows_(subCols_(data, colIndex, width), rowIndex, height)
),
label_, lambda(colIndex, subTable_(1, colIndex, 1, 1)),
headers, hstack(
subTable_(1, 1, 1, numColsToRepeat),
"Label",
subTable_(1, numColsToRepeat + 1, 1, numColsPerGroup)
),
numGroups, (columns(data) - numColsToRepeat) / numColsPerGroup,
groupIndices, sequence(1, numGroups, numColsToRepeat + 1, numColsPerGroup),
nullRow, tocol(iferror(ø), true),
unpivot, reduce(
headers, sequence(rows(data) - 1, 1, 2),
lambda(
result, rowIndex,
let(
firstCols, subTable_(rowIndex, 1, 1, numColsToRepeat),
stackResult, reduce(
nullRow, groupIndices,
lambda(rowStack, colIndex,
let(
group, subTable_(rowIndex, colIndex, 1, numColsPerGroup),
if(
single(group) = "",
rowStack,
vstack(rowStack, hstack(firstCols, label_(colIndex), group))
)
)
)
),
vstack(result, stackResult)
)
)
),
unpivot
)
要将公式应用于具有不同维度的数据表,请修改
data
、numColsToRepeat
和 numColsPerGroup
参数。当 data
是电子表格范围以及计算数组时,该公式将起作用。
该公式将清除列组第一列中缺少值的记录。如果您想保留这些记录,请将
if()
替换为其内部 vstack()
。
出于不为人知的原因,有些人更喜欢“单行”版本的公式,这些公式看起来就像昔日调制解调器的线路噪音。这些公式并不是“更有效”,但如果你想要一个不可读的版本,你可以使用这个:
=let(d,A1:K,f,2,g,3,r_,lambda(t,o,h,chooserows(t,sequence(h,1,o))),c_,lambda(t,o,w,choosecols(t,sequence(1,w,o))),s_,lambda(r,c,h,w,r_(c_(d,c,w),r,h)),l_,lambda(c,s_(1,c,1,1)),hr,hstack(s_(1,1,1,f),"Label",s_(1,f+1,1,g)),i,sequence(1,(columns(d)-f)/g,f+1,g),n,tocol(iferror(ø),true),reduce(hr,sequence(rows(d)-1,1,2),lambda(z,r,let(e,s_(r,1,1,f),s,reduce(n,i,lambda(t,c,let(x,s_(r,c,1,g),if(single(x)="",t,vstack(t,hstack(e,l_(c),x)))))),vstack(z,s)))))