일지/Proj4

데이터 약분류 시도(Archive, GEN 1 pipeline)

리나그(ReenAG) 2026. 2. 17. 22:16
728x90
반응형

 데이터에서 가장 유의미한 연속형 정보들을 전처리하고, 우선 주성분 분석을 통해서 Tron 네트워크의 주요한 통념, 가설 등이 잘 맞아 떨어지는지를 살펴보고자 한다. 

1. 데이터셋 전처리

1) parsing

일단 데이터셋은 tronsave에서 가져온 account(그러니까 tron 주소)의 상세정보에 대한 json파일들이다.
이를 다음과 같이 parsing하였다.

# 1. 핵심 파싱 함수 정의
parse_tron_data <- function(binary_blob) {
  # A. Arrow Binary -> R Raw Vector 변환
  raw_vec <- as.raw(binary_blob)
  
  # B. Gzip 압축 해제
  json_str <- rawToChar(memDecompress(raw_vec, type = "gzip"))
  
  # C. JSON 파싱
  data <- fromJSON(json_str, flatten = TRUE)
  
  # D. token 총 가격 추출
  tokens_df <- data$withPriceTokens
  
  # 데이터가 존재하고 데이터 프레임 형태인지 확인
  if (!is.null(tokens_df) && is.data.frame(tokens_df) && nrow(tokens_df) > 0) {
    tokens_df <- tokens_df[tokens_df$tokenAbbr != "trx", ]
    total_token_value <- sum(as.numeric(tokens_df$amount) * tokens_df$tokenPriceInTrx, na.rm = TRUE)
    tokens_count <- nrow(tokens_df)
    usdt_row <- tokens_df[tokens_df$tokenAbbr == "USDT", ]
    usdt_balance <- if(nrow(usdt_row) > 0) as.numeric(usdt_row$amount[1]) else 0
  } else {
    total_token_value <- 0
    tokens_count <- 0
    usdt_balance <- 0
  }
  
  # D. 필요한 Feature만 추출 후 Return 
  tibble(
    #1. Direct info
    #1-1. Tags
    is_red_tag = pluck(data, "redTag", .default = "") != "",
    #grey_tag = pluck(data, "greyTag", .default = NA_character_),
    #blue_tag = pluck(data, "blueTag", .default = NA_character_),
    #feedback_risk = pluck(data, "feedbackRisk", .default = FALSE),
    
    #1-2. Account Info
    activated = pluck(data, "activated", .default = FALSE),
    #is_verified = isTRUE(pluck(data, "vip", .default = FALSE)),
    account_type = pluck(data, "accountType", .default = 0),
    #has_announcement = nzchar(pluck(data, "announcement", .default = NA_character_)),
    date_created = anytime(pluck(data, "date_created", .default = 0)),
    
    #1-3. Permissions
    active_permissions = NROW(pluck(data, "activePermissions", .default = list())),
    #allowed_exchanges = NROW(pluck(data, "allowExchange", .default = list())),
    owner_permissions = NROW(pluck(data, "ownerPermission", "keys", .default = list())),
    
    #1-4. SR
    #representative = pluck(data, "representative", "enabled", .default = FALSE),
    
    #2. Balance info
    #this only shows trx
    balance = pluck(data, "balance", .default = 0) / 10^6,
    usdt_balance = usdt_balance,
    
    #2-1. Tokens
    tokens = tokens_count,
    total_token_value = total_token_value,
    
    #2-2. Asset Delegation
    #2-2-1. inward asset borrowing
    in_bd_sho_v1 = pluck(data, "acquiredDelegateFrozenForBandWidth", .default = 0),
    in_bd_val_v1 = pluck(data, "acquiredDelegatedFrozenBalanceForBandwidthValue", .default = 0),
    in_en_sho_v1 = pluck(data, "acquiredDelegateFrozenForEnergy", .default = 0),
    in_en_val_v1 = pluck(data, "acquiredDelegatedFrozenBalanceForEnergyValue", .default = 0),
    in_bd_sho_v2 = pluck(data, "acquiredDelegatedFrozenV2BalanceForBandwidth", .default = 0),
    in_bd_val_v2 = pluck(data, "acquiredDelegatedFrozenV2BalanceForBandwidthValue", .default = 0),
    in_en_sho_v2 = pluck(data, "acquiredDelegatedFrozenV2BalanceForEnergy", .default = 0),
    in_en_val_v2 = pluck(data, "acquiredDelegatedFrozenV2BalanceForEnergyValue", .default = 0),
    #2-2-2. outward asset lending
    out_bd_sho_v2 = pluck(data, "delegatedFrozenV2BalanceForBandwidth", .default = 0),
    out_bd_val_v2 = pluck(data, "delegatedFrozenV2BalanceForBandwidthValue", .default = 0),
    out_en_sho_v2 = pluck(data, "delegatedFrozenV2BalanceForEnergy", .default = 0),
    out_en_val_v2 = pluck(data, "delegatedFrozenV2BalanceForEnergyValue", .default = 0),
    out_bd_sho_v1 = pluck(data, "delegateFrozenForBandWidth", .default = 0),
    out_en_sho_v1 = pluck(data, "delegateFrozenForEnergy", .default = 0),
    #2-2-3. staking
    stk_bd_sho_v1 = pluck(data, "frozenForBandWidth", .default = 0),
    stk_bd_val_v1 = pluck(data, "frozenForBandwidthValue", .default = 0),
    stk_bd_sho_v2 = pluck(data, "frozenForBandWidthV2", .default = 0),
    stk_bd_val_v2 = pluck(data, "frozenForBandwidthV2Value", .default = 0),
    stk_bd_vas_v2 = pluck(data, "frozenForBandwidthV2ValueSum", .default = 0),
    stk_en_sho_v1 = pluck(data, "frozenForEnergy", .default = 0),
    stk_en_val_v1 = pluck(data, "frozenForEnergyValue", .default = 0),
    stk_en_sho_v2 = pluck(data, "frozenForEnergyV2", .default = 0),
    stk_en_val_v2 = pluck(data, "frozenForEnergyV2Value", .default = 0),
    stk_en_vas_v2 = pluck(data, "frozenForEnergyV2ValueSum", .default = 0),
    
    #3.Activity
    #3-1. Network usage
    free_net_used = pluck(data, "bandwidth", "freeNetUsed", .default = 0) > 0,
    net_used = (pluck(data, "totalNet", .default=600) - 
                  pluck(data, "totalNetRemaining", .default=600)) > 0,
    has_v2_widthdraw = pluck(data, "canWithdrawAmountV2", .default = 0) > 0,
    last_op_days_ago = as.numeric(difftime(Sys.time(), anytime(pluck(data, "latest_operation_time", .default = 0)/1000), units="days")),
    
    #3-2. Tx usage
    tx_count_tot = pluck(data, "totalTransactionCount", .default = 0),
    tx_count = pluck(data, "transactions", .default = 0),
    tx_count_in = pluck(data, "transactions_in", .default = 0),
    tx_count_out = pluck(data, "transactions_out", .default = 0),
    
    #3-3. Reward Related
    reward = pluck(data, "reward", .default = 0),
    reward_num = pluck(data, "rewardNum", .default = 0),
    vote_total = pluck(data, "voteTotal", .default = 0),
    
    #4.Misc
    #frozen_supply = NROW(pluck(data, "frozen_supply", .default = list())),
  )
}

 

이 위에서 주석처리된 변수, blue_tag, representative, frozen_supply등은 약 91만개의 주소들 중 변화를 전혀 관찰할 수 없었고, 따라서 차원의 저주를 방지할 겸, 제외한 것이다.

결국 제일 구체적인 정보는 stake와 관련된 정보, balance, account_type과 red_tag유무, 등등이라고 생각할 수 있다.

 2) 

 

 

2026년 9월 edit*

 일단 옛날 글 공개처리 할 겸 미리 덧붙이자면, tronscan에서 가져온 table data를 feature로 DBSCAN, 밀도 기반 클러스터링을 하려던 파이프라인의 결과이다. 몇 가지 문제점은 위와 같이 제대로 된 K를 짚기도 어렵고, 내가 만든 feature도 아니기 때문에 node를 제대로 분류하는 일도 한계가 있었다. 아무튼 이 이후에 내가 직접 block데이터를 가져오고 어떻게 transaction을 적재하는지, ETL에 관한 것들은 제대로 학습했으니 이것도 나름의 성장이라고 해야하나... 생각해보니 좋은 글감인 것 같긴하다. 한번 적어봐야할것 같다.

 

728x90
반응형