提问人:Phil 提问时间:11/13/2023 最后编辑:Phil 更新时间:11/14/2023 访问量:92
使用 Python(或 Power Query)将不同行中的数据转置到同一列,但每隔一段时间
Transpose data from different rows to the same column, but at a regular interval, using Python (or Power Query)
问:
所以,我有一个.xlsx数据集,我称之为“源”数据集。 “源”数据集有数百行,其中包含有关每个物种昆虫数量的信息。 数据集每列的标题都具有每个物种的名称。 我需要将此数据转置到另一个数据集的同一列中,也是一个 .xlsx 文件,我称之为“命运”数据集。
我需要创建一个循环来执行以下操作:
- 从单元格“A2”开始,遍历“源”数据集每行的列“A”,并验证是否存在数据。
- 如果单元格“A2”中有数据,则将整个信息从单元格“B2”复制到单元格“E2”。
- 将复制的数据转置到“命运”数据集的列“C”中,从单元格“C2”开始
- 然后,在下一次迭代中,验证源数据集的单元格“A3”中是否有数据,并将整个信息从单元格“B3”复制到单元格“E3”
- 然后将复制的数据转置到“命运”数据集的“C”列,但这次从单元格“C2”下方的 7 个单元格开始,即在单元格“C8”处转置。
- 在下一次迭代中,始终在上次转置数据下方 7 个单元格处转置来自“源”数据集的数据。
我知道这有点令人困惑,但应该通过下面的示例来澄清:
“源”数据集如下所示:
Point|Spongillidae|Olindiidae|Hydridae|Oceaniidae|
:------|---------:|---------:|-------:|---------:|
MK1 |3 | |1 |5 |
RT2 |2 |7 | | |
GT3 |10 |1 |6 |15 |
当前的“命运”数据集目前如下所示:
Point| Species |Value |
:----|:----------:|-----:|
MK1 |Spongillidae| |
MK1 |Olindiidae | |
MK1 |Hydridae | |
MK1 |Oceaniidae | |
MK1 |Colletor |TG |
MK1 |Habitat |Edge |
RT2 |Spongillidae| |
RT2 |Olindiidae | |
RT2 |Hydridae | |
RT2 |Oceaniidae | |
RT2 |Colletor |DG |
RT2 |Habitat |Riffle|
GT3 |Spongillidae| |
GT3 |Olindiidae | |
GT3 |Hydridae | |
GT3 |Oceaniidae | |
GT3 |Colletor |JB |
GT3 |Habitat |Riffle|
最后,“命运”数据集应如下所示:
Point| Species |Value |
:----|:----------:|-----:|
MK1 |Spongillidae|3 |
MK1 |Olindiidae | |
MK1 |Hydridae |1 |
MK1 |Oceaniidae |5 |
MK1 |Colletor |TG |
MK1 |Habitat |Edge |
RT2 |Spongillidae|2 |
RT2 |Olindiidae |7 |
RT2 |Hydridae | |
RT2 |Oceaniidae | |
RT2 |Colletor |DG |
RT2 |Habitat |Riffle|
GT3 |Spongillidae|10 |
GT3 |Olindiidae |1 |
GT3 |Hydridae |6 |
GT3 |Oceaniidae |15 |
GT3 |Colletor |JB |
GT3 |Habitat |Riffle|
我希望有人能帮我找到解决这个问题的方法。
答:
0赞
arigo
11/13/2023
#1
请确保您的初始数据从 Sheet1 的左上角开始 (A1=“Point”)。
在Excel中创建一个宏并将其命名为Sub change_format(),并将以下代码粘贴在“Sub change_format()”和“End sub”之间。然后运行它,您将在 Sheet2 中获得结果。确保以 .xlsm 格式保存您的文件!!
i = 1 'First row of Sheet1 for reading
r = 2 'First row of Sheet2 for writing
'Find number of Points
While Sheet1.Cells(i, 1) <> ""
i = i + 1
Wend
pnt = i - 2
For p = 1 To pnt 'Points
For s = 2 To 7 'Species
cur_type = Sheet1.Cells(p + 1, 1) 'Current type
cur_spc = Sheet1.Cells(1, s) 'Current species
cur_val = Sheet1.Cells(p + 1, s) 'Current value
Sheet2.Cells(1, 1) = "Point"
Sheet2.Cells(1, 2) = "Species"
Sheet2.Cells(1, 3) = "Value"
Sheet2.Cells(r, 1) = cur_type
Sheet2.Cells(r, 2) = cur_spc
Sheet2.Cells(r, 3) = cur_val
r = r + 1
Next s
Next p
1赞
Ron Rosenfeld
11/13/2023
#2
这也可以使用 Windows Excel 2010+ 和 Microsoft 365(Windows 或 Mac)中提供的 Power Query 完成
使用 Power Query
- 选择数据表中的某个单元格
Data => Get&Transform => from Table/Range
- 当 PQ 编辑器打开时:
Home => Advanced Editor
- 记下第 2 行中的表名
- 粘贴下面的 M 代码来代替您看到的内容
- 将第 2 行中的表名称改回最初生成的名称。
- 阅读评论并探索以了解算法
Applied Steps
M代码
let
//Read in Source Table
// Change depending on your actual data source
Source = Excel.CurrentWorkbook(){[Name="Source"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,
{{"Point", type text}} & List.Transform(List.RemoveFirstN(Table.ColumnNames(Source),1), each {_, Int64.Type})),
//Unpivot to produce a three column table
#"Unpivot Source" = Table.UnpivotOtherColumns(#"Changed Type",{"Point"},"Species","Value"),
//Read in Destiny Table
// Change depending on your actual data source
Source2 = Excel.CurrentWorkbook(){[Name="Destiny"]}[Content],
//Add Index Column for Sorting
#"Added Index" = Table.AddIndexColumn(Source2, "Index", 0, 1, Int64.Type),
#"Destiny Typed" = Table.TransformColumnTypes(#"Added Index",{
{"Point", type text}, {"Species", type text},{"Value", type any}}),
//Join the two tables
joined = Table.NestedJoin(#"Destiny Typed",
{"Point","Species"},#"Unpivot Source",{"Point","Species"},"Join",JoinKind.FullOuter),
//Replace the null Values
#"Replace null Values" = Table.ReplaceValue(
joined,
each [Value],
each if [Value] = null then [Join][Value]{0} else [Value],
Replacer.ReplaceValue,
{"Value"}
),
#"Removed Columns" = Table.RemoveColumns(#"Replace null Values",{"Join"}),
#"Sorted Rows" = Table.Sort(#"Removed Columns",{{"Index", Order.Ascending}}),
#"Removed Columns1" = Table.RemoveColumns(#"Sorted Rows",{"Index"})
in
#"Removed Columns1"
注意:实际上,您可以从一个包含每个点
的 Colletor
和 Habitat
的源表开始,然后生成整个 Destiny 表。
然后,一个简单的表格将生成:UnPivot
Destiny
et
//change next line to reflect actual data source
Source = Excel.CurrentWorkbook(){[Name="Source14"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,
{{"Point", type text}, {"Colletor", type text}, {"Habitat", type text}}
& List.Transform(List.RemoveFirstN(Table.ColumnNames(Source),3), each {_, Int64.Type})),
//Unpivot all except the Point Column
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"Point"}, "Attribute", "Value")
in
#"Unpivoted Other Columns"
如果这是可行的,可以很容易地修改代码以包含“空白”条目以及所需的排序顺序。
上一个:打印转置矩阵时出现的问题
评论