Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 3 additions & 23 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
## 2026-06-30 - Pre-calculate Theta Variables to Avoid Redundant MAP estimation
**Learning:** `mirt::fscores(..., method = 'MAP')` is called redundantly multiple times in `R/aFIPC.R`. It's an expensive operation and avoiding duplicate calls by pre-calculating and reusing the variables significantly improves performance.
**Action:** Always pre-calculate and reuse the resulting Theta variables rather than calling it redundantly.

## 2026-06-30 - Preserve numerical output when caching MAP scores
**Learning:** `fscores(..., method = 'MAP')` caching is safe only when the cached theta values are passed to the same downstream `expected.test()` calls without changing model state or estimation options.
**Action:** Treat MAP-score caching as a pure reuse optimization and keep true-parameter recovery tests in place when changing calibration code.

## 2024-05-18 - R 언어에서 루프 내 정규식 탐색 병목 최적화
**Learning:** R에서 데이터 프레임의 크기가 커질수록 루프 내에서 컬럼명을 추출하고 정규식을 이용해(`grep`) 문자열을 탐색하는 작업이 상당한 성능 오버헤드를 발생시킨다. 특히 O(N) 탐색을 루프 안에서 반복할 경우 O(N^2)의 비효율성을 초래한다.
**Action:** 루프 내부에서 자주 호출되는 컬럼명이나 데이터 프레임 구조 탐색을 루프 밖으로 빼서 한 번만 계산하여 벡터로 저장하도록 한다. 정규식보다는 완전 일치 탐색(`%in%`, `match`)이 가능하도록 벡터 연산을 활용해 O(1) 수준으로 성능을 끌어올려야 한다.

## 2026-06-30 - Keep paired form item names when removing grep
**Learning:** Replacing regex lookups with direct name references must still respect that the same common item can have different column names in the new and old forms.
**Action:** Resolve names independently with each form's declared common-item vector before subsetting model data.

## 2026-06-30 - Avoid factor allocation for response-category counts
**Learning:** `levels(as.factor(x))` allocates a factor just to count response categories, which is unnecessary in repeated common-item loops.
**Action:** Use `length(na.omit(unique(x)))` for category-count comparisons while preserving the existing exact item-name matching.

## 2026-06-30 - Preserve NA handling when removing factor conversions
**Learning:** `levels(as.factor(x))` excludes missing responses from the category count, so a faster replacement must not count `NA` as an extra response category.
**Action:** Keep `na.omit(unique(x))` rather than plain `unique(x)` in response-category comparisons.
## 2024-07-04 - R 언어에서 루프 내 데이터 프레임 탐색 병목 최적화
**Learning:** R에서 루프를 돌면서 매번 데이터 프레임을 서브셋팅(subsetting)하는 작업은 복사 오버헤드로 인해 매우 느려질 수 있습니다. 특히 공통 문항 수가 많아질 경우 O(N^2)의 비효율을 초래합니다.
**Action:** 루프 내에서 수행하던 데이터 프레임 조회를 루프 외부에서 한 번에 `as.character(unlist(...))`로 처리하는 벡터 연산으로 변경하여 타입 변환 없이 O(1) 수준으로 성능을 크게 향상시킬 수 있습니다.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export(autoFIPC)
export(surveyFA)
import(mirt)
importFrom(stats,factanal)
importFrom("stats", "na.omit")
12 changes: 4 additions & 8 deletions R/aFIPC.R
Original file line number Diff line number Diff line change
Expand Up @@ -692,16 +692,12 @@ autoFIPC <-
print(modIPD_DIF)
print(CommonItemList_NOIPD)

# ⚡ Bolt: 루프 내에서 데이터 프레임을 서브셋팅(subsetting)하는 O(N) 연산을
# unlist()를 활용한 벡터화된(vectorized) O(1) 연산으로 대체하여 성능 향상
ActualoldFormCommonItem <-
vector(length = length(CommonItemList_NOIPD))
as.character(unlist(IPDItemList[1, CommonItemList_NOIPD]))
ActualnewFormCommonItem <-
vector(length = length(CommonItemList_NOIPD))
for (i in 1:length(CommonItemList_NOIPD)) {
ActualoldFormCommonItem[i] <-
as.character(IPDItemList[CommonItemList_NOIPD][1, i])
ActualnewFormCommonItem[i] <-
as.character(IPDItemList[CommonItemList_NOIPD][2, i])
}
as.character(unlist(IPDItemList[2, CommonItemList_NOIPD]))

message('ActualoldFormCommonItem: ', ActualoldFormCommonItem)
message('ActualnewFormCommonItem: ', ActualnewFormCommonItem)
Expand Down
Loading