지금까지 배운 R의 기본 1차원 벡터(Vector)는 반드시 태생부터 “단일 타입(예: 모두 숫자이거나 모두 문자만 허용)”으로만 강제로 묶여야 한다는 답답함이 있었습니다. 그러나 우리가 처리할 현실 세계의 데이터는 절대 그렇지 않죠. “이름상자(문자), 회원번호상자(숫자), 구매이력이나 장바구니 내역 모음(또 다른 벡터 형태)” 등 서로 전혀 다른 온갖 복잡한 유형의 정보들을 하나의 거대한 개인별 쇼핑 바구니에 전부 넣고 들고 다녀야 할 때가 무조건 찾아옵니다.
이럴 때 사용하는 R의 궁극적이고 이질적인 데이터 컨테이너가 바로 리스트(List)입니다. 리스트는 R 데이터 구조의 궁극적 종착역이자, 데이터 프레임을 만들기 위한 뼈대(핵심 엔진)입니다. 이 포스트 하나로 완벽히 리스트를 이해해 봅시다!
1. 모든 이질적인 것을 다 담아내는 마법의 바구니, list()
동일한 녀석들만 모으던 벡터가 c()로 묶였다면, 다양한 것을 한 번에 품는 리스트는 list()라는 전용 결합 함수로 생성합니다.
mylist <- list(
name = "issac", # 문자 데이터 달랑 한 개
id = 30096, # 숫자 데이터 한 개
order = c(1, 2) # 길이가 2개인 또 다른 벡터 집합
)
mylist
> $name
> [1] "issac"
>
> $id
> [1] 30096
>
> $order
> [1] 1 2
생성 후 곧바로 콘솔에 출력해 보면, 놀랍게도 각각 지어진 방($name, $id, $order)에 각기 다른 형태(문자/숫자)와 심지어 길이(데이터 수량이 1개/2개)가 다름에도 에러 없이 너무나 평화롭게 공존하고 있는 것을 생생하게 보실 수 있습니다. 이게 만약 기존의 c() 구조였다면 전부 강제로 문자로 역변환되어버리거나 충돌 강제 종료 에러가 났을 일입니다.
2. 리스트 방 문을 여는 3가지 마스터키 (인덱싱 권법)
리스트 안에 보관된 세부 데이터들만 입맛에 맞게 정교히 접근하려면 크게 세 가지 열쇠를 나눠 쓸 수 있습니다. 초보 시절엔 이 부분이 구분이 안 가 가장 헷갈리지만 매우 중요한 기본기입니다.
① 가장 직관적인 $ (달러) 기호 열쇠 사용하기
앞서 생성했던 것처럼 각 칸마다 태그(이름표)가 견고히 붙은 Named 리스트라면, 달러 기호($)를 통해 다이렉트로 그 방의 철문을 열고 접근할 수 있습니다. 거의 90% 이상 엑셀 열 데이터 접근에 쓰이는 방식입니다.
mylist$name
> [1] "issac"
mylist$order
> [1] 1 2
② 리스트 방 번호로 직접 내부 침투 [[]] (이중 대괄호)
만약 너무 데이터가 방대해 태그이름을 다 기억하지 못하지만, 이게 첫 번째 방이라는 방 번호(순서)를 정확히 안다면? 이중 대괄호 [[ ]] 안에 숫자를 넣어 해당 원소 알맹이(본질) 그 자체의 데이터형으로 끄집어냅니다.
mylist[[1]]
> [1] "issac"
③ 리스트 포장 상태 그대로 배달받기 [] (단일 대괄호)
아주 헷갈리실 수 있는데, 이중 대괄호 [[]]가 택배 상자의 포장을 북북 찢어 까서 알맹이만 쏙 빼내는 거라면, 겉의 단일 대괄호 []는 내용물은 건들지 않고 상자(리스트 속성)는 여전히 포장된 상태로 부분집합만 잘라서 가져옵니다.
mylist["name"]
> $name
> [1] "issac"
결과물 최상단에 $name이라는 라벨이 안 풀리고 그대로 딸려오는 것이 보이시나요? 즉, 이것의 정체는 방 1개짜리 ‘미니 리스트’가 반환된 것입니다.
💡 핵심 메모리아 요약:
[[]]vs[]의 결정적 차이
–[[]]: 껍질을 까서 내용물(원소) 그 자체를 가져옴 (문자면 문자로 반환).
–[]: 껍질(리스트 상태 구조)을 무조건 유지한 채 바구니만 작게 잘라옴.
3. 리스트 방 수정 및 과감하게 삭제하기
데이터 전처리 중 새로운 속성(열)을 집어 넣거나 필요 없어진 빅테이터 기록 찌꺼기를 지울 때도 마치 변수에 값을 넣듯 $만 쓰면 다이렉트 처리가 됩니다.
# 새로운 방 이름(연락처 폰번호) 기재하여 추가 런칭!
mylist$phone <- "010-0000-0000"
# 기존 방(아이디) 내용을 최신 내역으로 덮어 바꾸기!
mylist$id <- 99999
# 불필요해진 방 자체를 통째로 폭파시켜 지우기! (NULL 사용)
mylist$order <- NULL
4. 너무 복잡한 놈들을 단숨에 펴버리기 전략: unlist()
웹 시스템과 API 연결을 통해 돌려받은 초거대 리스트 구조(예: JSON 포맷)가 너무 복잡해서 속이 터질 떄가 있습니다. 어차피 안에 등재된 건 숫자나 문자열 뿐이니 그냥 일렬로 된 평평한 단순 벡터(Vector)로 전부 다 평평하게 펴버리고 싶을 때가 있습니다.
unlist(mylist)
> name id phone
> "issac" "99999" "010-0000-0000"
이 마법의 unlist() 함수 한 방이면 아무리 겹겹이 계층형으로 쌓인 수천 겹 박스들도 단번에 분해해서 1차원의 쫙 펴진, 엑셀 1열 같은 단순한 데이터 형태로 만들어줍니다. (웹 브라우저 크롤링 원시 데이터나 복잡한 LLM API 결과값을 정리할 때 완전 구세주 역할을 합니다!)
여러분이 RStudio나 Positron에서 만나는 모든 데이터프레임과 시계열 모델링 통계 결과물 리포트는 사실 다 이 리스트(List) 뼈대 구조로 되어 있습니다. 오늘 배운 $ 연산자와 [[]] 까내기 권법을 온몸으로 기억하신다면 앞으로 R 에러 메시지 분석에서 막혀 좌절하실 일은 단언컨대 없습니다!
당신이 좋아할 만한 콘텐츠
by Google Adsense