英文:
Is there a way in Excel to read through 3 columns simultaneously and add the sequence of specific occurrences in a new column?
问题
我有一个包含大约60,000行的大型电子表格。
它们是来自98个摄像机陷阱的事件记录。我有一个名为"Station Number"的列,其中包含分配给每个摄像机陷阱的编号(这些编号从1到98,并且在该列中每个编号都有多个出现,因为每个摄像机陷阱有多行/摄像机图像)。
现在,我想找出这些摄像机陷阱上男性和女性出现的顺序。
我手动记录了这50,000张图像中的男性和女性出现情况,并分别放在两个单独的列中,分别称为"N_Male"和"N_Female"。当图像中出现男性时,"N_Male"列中的该行标记为"1",女性出现时也是如此。
我现在希望找到一种方法来获取每个98个站点的男性和女性出现顺序,可以是包含所有信息的新表/列,也可以是每个摄像机的单个输出,例如"Camera 1: MFMMFFFMFMMMF...等"。
我开始在两个工作表中手动完成这个任务,但意识到这将花费我相当多的时间(有超过50,000行)。是否有办法在Excel中使用VBA、宏或公式等自动化这个过程?请参考下面电子表格的前几行示例:
Station Number | N_Male | N_Female |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
1 | 1 | 0 |
1 | 0 | 0 |
2 | 0 | 1 |
2 | 0 | 0 |
2 | 0 | 1 |
3 | 1 | 0 |
4 | 1 | 0 |
4 | 1 | 0 |
4 | 0 | 0 |
4 | 0 | 1 |
上述示例的输出如下:
Camera 1: MFM
Camera 2: FF
Camera 3: M
Camera 4: MMF
我首先尝试手动完成(非常耗时)。然后尝试使用COUNTIFS公式。它成功地读取了第一列,并理解了男性和女性列中的不同出现情况,但是记录的是数值。然后我考虑使用CONCAT函数,但由于输入是数值(例如"N_Male = 1"),它无法完全理解。也许可以使用一些替代的concat函数?或者textsplit?
我对Excel中的这些函数真的很陌生,所以非常感谢任何建议或指导。
英文:
I have a large spreadsheet containing around 60,000 rows.
They are records of events from 98 camera traps. I have a column called "Station Number" which contains the number assigned to each camera trap (these are numbered from 1-98 and there are multiple occurrences of each number in this column as there are multiple rows/camera images from each camera trap).
I now would like to find the sequence of male and female occurrences on these camera traps.
I manually recorded these for the 50,000 images into two separate columns called "N_Male" and "N_Female". When a male appears in the images, this row in the "N_Male" column was marked as "1", and the same for when females appear.
I am now looking to find a way to obtain the sequence/order of male and female occurrences for each of the 98 stations with either an output that is either a new table/columns with all of the information or one single output for each camera like "Camera 1: MFMMFFFMFMMMF...etc".
I started doing this manually in two sheets but realized it will take me a considerable amount of time (there are over 50,000 rows). Is there any way to automate this using VBA or macro or formulas etc in Excel? Please see the example below of the first rows of the spreadsheet:
Station Number | N_Male | N_Female |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
1 | 1 | 0 |
1 | 0 | 0 |
2 | 0 | 1 |
2 | 0 | 0 |
2 | 0 | 1 |
3 | 1 | 0 |
4 | 1 | 0 |
4 | 1 | 0 |
4 | 0 | 0 |
4 | 0 | 1 |
Example of the output from the above:
Camera 1: MFM
Camera 2: FF
Camera 3: M
Camera 4: MMF
I tried first doing this manually (very time consuming). But then tried using COUNTIFS formulas. It was successfully reading through the first columns and understanding the different occurrences in the male and female columns, but was recording this instead numerically. I then considered using CONCAT and tried it but as the input is numerical (e.g "N_Male = 1), it wasn't understanding it fully. Perhaps some substitute concat function could work? or textsplit?
I am really a newbie to these functions in Excel so any advice or guidance would be hugely appreciated.
答案1
得分: 4
另一种使用公式的版本:
=LET(a,A2:A13,
b,B2:B13,
c,C2:C13,
d,IFERROR(IFS(b,"M",c,"F"),""),
u,UNIQUE(a),
m,MAP(u,LAMBDA(y,CONCAT(FILTER(d,a=y)))),
HSTACK(u,m))
英文:
Another version using formula:
=LET(a,A2:A13,
b,B2:B13,
c,C2:C13,
d,IFERROR(IFS(b,"M",c,"F"),""),
u,UNIQUE(a),
m,MAP(u,LAMBDA(y,CONCAT(FILTER(d,a=y)))),
HSTACK(u,m))
答案2
得分: 3
使用公式:
=LET(
rng,A:C,
flt,DROP(FILTER(rng,TAKE(rng,,1)<>""),1),
a,TAKE(flt,,1),
bc,TAKE(flt,,-2),
unq,UNIQUE(a),
cnc,BYROW(unq,
LAMBDA(r,CONCAT(BYROW(FILTER(bc,a=r),
LAMBDA(x,IF(TAKE(x,,1)=1,"M",IF(TAKE(x,,-1)=1,"F",""))))))),
HSTACK(unq,cnc))
英文:
With Formula:
=LET(
rng,A:C,
flt,DROP(FILTER(rng,TAKE(rng,,1)<>""),1),
a,TAKE(flt,,1),
bc,TAKE(flt,,-2),
unq,UNIQUE(a),
cnc,BYROW(unq,
LAMBDA(r,CONCAT(BYROW(FILTER(bc,a=r),
LAMBDA(x,IF(TAKE(x,,1)=1,"M",IF(TAKE(x,,-1)=1,"F",""))))))),
HSTACK(unq,cnc))
答案3
得分: 3
加入比赛
=LET(data,A2:C13,nCol,1,mCol,2,fCol,3,TwoCols,FALSE,mfVal,1,
lDel,"相机 ",mDel,": ",dvDel,"",dmVal,"男",dfVal,"女",dnVal,"",
su,INDEX(data,,nCol),sm,INDEX(data,,mCol),sf,INDEX(data,,fCol),
du,UNIQUE(su),
df,IF(sm+sf=mfVal,IF(sm=mfVal,dmVal,dfVal),dnVal),
dv,BYROW(du,LAMBDA(r,TEXTJOIN(dvDel,1,FILTER(df,su=r)))),
dr,IF(TwoCols,HSTACK(lDel&du,dv),lDel&du&mDel&dv),
dr)
英文:
Join Matches
=LET(data,A2:C13,nCol,1,mCol,2,fCol,3,TwoCols,FALSE,mfVal,1,
lDel,"Camera ",mDel,": ",dvDel,"",dmVal,"M",dfVal,"F",dnVal,"",
su,INDEX(data,,nCol),sm,INDEX(data,,mCol),sf,INDEX(data,,fCol),
du,UNIQUE(su),
df,IF(sm+sf=mfVal,IF(sm=mfVal,dmVal,dfVal),dnVal),
dv,BYROW(du,LAMBDA(r,TEXTJOIN(dvDel,1,FILTER(df,su=r)))),
dr,IF(TwoCols,HSTACK(lDel&du,dv),lDel&du&mDel&dv),
dr)
答案4
得分: 2
以下例程创建一个以相机编号为键的字典。它首先将所有数据读入数组以加快处理速度,然后逐行循环数据并为每一行创建一个字符串(存储在变量sequence
中)。
由于我一直倡导早期绑定:在您的VBA项目中添加对Microsoft Scripting.Library的引用,以便您可以使用Dictionary类。
Function createCameraDict(r As Range) As Scripting.Dictionary
Dim cameraDict As New Dictionary
Dim data As Variant, row As Long
data = r.Value ' 从数据创建一个二维数组
Dim camera As String, sequence As String
For row = 2 To UBound(data, 1)
camera = data(row, 1)
' 从该行的第2和第3个单元格创建一个类似于"MF"的字符串。
sequence = String(data(row, 2), "M") & String(data(row, 3), "F")
If sequence <> "" Then
' 将序列添加到该相机的已有序列中。
' (如果字典中缺少相机,则会自动添加相机)
cameraDict(camera) = cameraDict(camera) & sequence
End If
Next row
Set createCameraDict = cameraDict
End Function
现在一个测试可以像这样:
Sub test()
Dim d As Scripting.Dictionary
Set d = createCameraDict(ThisWorkbook.Sheets(1).Cells(1, 1).CurrentRegion)
Dim camera
For Each camera In d.Keys
' (在这里,您可以将数据写入工作表或任何您想要的地方。)
Debug.Print "相机 " & camera & ": " & d(camera)
Next
End Sub
英文:
The following routine create a dictionary with the camera number as key. It first reads all the data into an array to speed up the process, then loops over the data row by row and creates a string (in variable sequence
) for every row.
As I always advocate for early binding: Add a reference to the Microsoft Scripting.Library in your VBA project so that you can use the Dictionary class.
Function createCameraDict(r As Range) As Scripting.Dictionary
Dim cameraDict As New Dictionary
Dim data As Variant, row As Long
data = r.Value ' Creates a 2-dimensional array from the data
Dim camera As String, sequence As String
For row = 2 To UBound(data, 1)
camera = data(row, 1)
' Create a string like "MF" from cells 2 and 3 of that row.
sequence = String(data(row, 2), "M") & String(data(row, 3), "F")
If sequence <> "" Then
' Add the sequence to the already existing sequence for that camera.
' (camera will be added automatically if missing in the Dict)
cameraDict(camera) = cameraDict(camera) & sequence
End If
Next row
Set createCameraDict = cameraDict
End Function
Now a test could look like
Sub test()
Dim d As Scripting.Dictionary
Set d = createCameraDict(ThisWorkbook.Sheets(1).Cells(1, 1).CurrentRegion)
Dim camera
For Each camera In d.Keys
' (Here you could write the data into a sheet or whatever you want.)
Debug.Print "Camera " & camera & ": " & d(camera)
Next
End Sub
答案5
得分: 0
' 创建一个包含98个条目的二维数组(索引 + 字符串),然后将其写入I2单元格。
Sub createSequence()
Dim xLAppL As Excel.Application: Set xLAppL = GetObject(, "Excel.Application")
Dim wrkBk As Excel.Workbook: Set wrkBk = xLAppL.ActiveWorkbook
Dim wrksH As Worksheet: Set wrksH = wrkBk.ActiveSheet
Dim wrksHTrgt As Worksheet: Set wrksHTrgt = wrkBk.Sheets("Sheet8")
Dim rngStationArr() As Variant: rngStationArr = wrksH.Range("a1").CurrentRegion
Dim i As Long
Dim stationCount As Long
Dim stationStr() As String: ReDim stationStr(1 To 98, 1 To 2) ' 在这里编辑组的数量
For i = 2 To UBound(rngStationArr, 1)
stationCount = rngStationArr(i, 1)
Dim stationData As String: stationData = stationStr(stationCount, 2)
stationStr(stationCount, 1) = stationCount
If rngStationArr(i, 2) = 1 Then
stationStr(stationCount, 2) = stationData & "M"
ElseIf rngStationArr(i, 3) = 1 Then
stationStr(stationCount, 2) = stationData & "F"
End If
Next i
wrksHTrgt.Range("I2").Resize(UBound(stationStr, 1), UBound(stationStr, 2)).Value2 = stationStr
End Sub
这段代码创建了一个名为stationStr
的二维数组,包含98个条目。每个条目由索引和字符串组成。然后,根据条件将相应的字符串添加到数组中的每个条目。最后,将数组的内容写入目标工作表的I2单元格及其后续单元格中。
请注意,此代码是使用VBA编写的,用于在Excel中执行特定的操作。
英文:
A two-dimensional array (index + string) for the 98 entries is created, then it is written in I2.
Sub createSequence()
Dim xLAppL As Excel.Application: Set xLAppL = GetObject(, "Excel.Application")
Dim wrkBk As Excel.Workbook: Set wrkBk = xLAppL.ActiveWorkbook
Dim wrksH As Worksheet: Set wrksH = wrkBk.ActiveSheet
Dim wrksHTrgt As Worksheet: Set wrksHTrgt = wrkBk.Sheets("Sheet8")
Dim rngStationArr() As Variant: rngStationArr = wrksH.Range("a1").CurrentRegion
Dim i As Long
Dim stationCount As Long
Dim stationStr() As String: ReDim stationStr(1 To 98, 1 To 2) 'edit here the number of groups
For i = 2 To UBound(rngStationArr, 1)
stationCount = rngStationArr(i, 1)
Dim stationData As String: stationData = stationStr(stationCount, 2)
stationStr(stationCount, 1) = stationCount
If rngStationArr(i, 2) = 1 Then
stationStr(stationCount, 2) = stationData & "M"
ElseIf rngStationArr(i, 3) = 1 Then
stationStr(stationCount, 2) = stationData & "F"
End If
Next i
wrksHTrgt.Range("I2").Resize(UBound(stationStr, 1), UBound(stationStr, 2)).Value2 = stationStr
End Sub
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论