분석 질문을 먼저 정한다
"AI로 분석해줘"가 아니라 "조건별 차이", "변수 관계", "미래 예측", "유형 분류", "패턴 발견" 중 무엇을 원하는지 정합니다.
이 페이지는 탐구 주제 목록이 아니라, 실험데이터·공공데이터·센서로그·이미지·텍스트를 어떤 AI 분석 방법으로 다룰지 구체적으로 안내하는 분석법 중심 웹페이지입니다. AI는 답을 대신 쓰는 도구가 아니라, 분석법 선택·코드 생성·오류 검토·해석 정교화를 돕는 데이터 분석 파트너로 사용합니다.
좋은 분석은 복잡한 모델을 쓰는 것이 아니라, 데이터의 구조와 질문에 맞는 방법을 고르고, 결과를 검증 가능한 근거로 해석하는 것입니다.
"AI로 분석해줘"가 아니라 "조건별 차이", "변수 관계", "미래 예측", "유형 분류", "패턴 발견" 중 무엇을 원하는지 정합니다.
AI가 제안한 전처리를 적용하더라도 원자료, 전처리본, 분석 코드, 그래프를 분리해 재현 가능하게 관리합니다.
훈련/검증 분리, 교차검증, 잔차분석, 오분류 분석, 외부 검증을 통해 결과가 우연인지 확인합니다.
AI는 코드와 해석 초안을 만들 수 있지만, 단위·측정 맥락·변수 의미·인과 해석은 학생이 직접 판단해야 합니다.
각 단계마다 AI에게 요청할 일과 학생이 직접 확인할 일을 분리해야 합니다.
파일을 통째로 던지기보다 열 이름, 샘플 10행, 측정 방법, 단위, 연구 목적을 함께 제공합니다. 개인정보·민감정보는 마스킹하거나 제외합니다.
결측치, 중복, 이상치, 단위 불일치, 범주 오타, 날짜 형식 오류를 먼저 찾습니다.
설명, 비교, 관계, 예측, 분류, 패턴 발견, 최적화 중 하나로 목적을 분류합니다. 목적이 바뀌면 분석법도 바뀝니다.
한 가지 방법으로 바로 결론을 내리지 말고, 쉬운 방법과 복잡한 방법을 함께 비교합니다.
AI에게 Python 코드를 요청하되, 각 코드 줄의 목적과 입력·출력 형태를 설명하게 합니다. 라이브러리 버전과 한국어 처리 환경을 명시하면 오류가 줄어듭니다.
수치만 보지 말고 분포, 산점도, 잔차, 오차막대, 오분류 사례를 함께 봅니다. 그래프 제목·축·단위·표본 수·오차막대 종류를 반드시 표기합니다.
데이터 누수, 과적합, 표본 불균형, 이상치 영향, 인과 과장, 그래프 왜곡, 코드 실행 결과 일치성을 점검합니다.
"좋아졌다"가 아니라 "A 조건의 평균이 B보다 2.3 높고 표준편차는…"처럼 수치 근거를 포함합니다. 인과가 아니라 관계·경향·가능성으로 표현합니다.
프롬프트, AI 제안, 직접 검증한 내용, 수정한 내용, 최종 반영 여부를 기록합니다. 보고서에 AI 사용 사실을 명시하는 것은 학술 정직성의 출발점입니다.
데이터 분석은 질문의 유형에 따라 방법이 달라집니다. 아래 표를 보고 먼저 큰 방향을 정하세요.
| 분석 목적 | 데이터 형태 | 추천 분석법 | 해석 핵심 |
|---|---|---|---|
| 값을 요약하고 싶다 | 수치형 1~2개 | 기술통계, 히스토그램, boxplot | 평균만 쓰지 말고 분포와 산포를 함께 보여준다. |
| 조건별 차이를 비교하고 싶다 | 집단 변수 + 수치형 결과 | 오차막대, 평균 비교, 효과크기, ANOVA | 반복 수와 표준편차를 반드시 제시한다. |
| 두 변수 관계를 보고 싶다 | 연속형 변수 2개 이상 | 산점도, 상관분석, 회귀분석, 잔차분석 | 상관과 인과를 구분한다. |
| 결과를 예측하고 싶다 | 입력 변수 + 목표값 | 회귀모델, 랜덤포레스트, 교차검증 | 훈련/검증 분리를 먼저 한다. |
| 유형을 자동 분류하고 싶다 | 특징값 + 라벨 | 로지스틱 회귀, 의사결정나무, 혼동행렬 | 정확도만 보지 말고 오분류를 본다. |
| 숨은 패턴을 찾고 싶다 | 라벨 없는 다변량 데이터 | PCA, K-means, 군집 프로파일링 | 군집 이름은 원자료 근거로 붙인다. |
| 시간 흐름을 분석하고 싶다 | 시간 + 측정값 | 이동평균, 추세, lag 분석, 이상 구간 탐지 | 무작위 셔플을 피하고 시간순으로 검증한다. |
| 텍스트를 분석하고 싶다 | 문장, 기사, 서술형 응답 | 키워드 빈도, n-gram, TF-IDF, 문서 군집 | 한국어는 형태소 분석이 필요할 수 있다. |
| 이미지를 수치화하고 싶다 | 사진, 현미경 이미지, 타임랩스 | RGB 평균, 임계값 분할, 객체 계수, 면적 측정 | 조명, 거리, 기준자 조건을 통제한다. |
| 최적 조건을 찾고 싶다 | 조건 조합 + 결과값 | 격자 탐색, 민감도 분석, 시나리오 비교 | 측정 범위 밖으로 결론을 확장하지 않는다. |
| 분석 결과를 검증하고 싶다 | 분석 결과, 모델 출력 | 잔차분석, 교차검증, 외부 검증, AI 답변 점검 | 한 번의 결과로 단정하지 않는다. |
데이터 유형과 목표를 고르면 분석법 도감에서 적절한 방법을 자동으로 추천합니다.
분석법을 이름만 아는 데서 멈추지 않도록, 언제 쓰는지·AI에게 무엇을 시킬지·학생이 무엇을 검증할지까지 정리했습니다. 카드를 클릭하면 자세한 설명과 복사 가능한 프롬프트가 열립니다.
자료가 어떤 형태인지 알면 분석의 절반은 정해집니다. 아래 루트를 따라 AI에게 구체적으로 요청하세요.
코드는 그대로 복사해서 시작하되, 열 이름과 파일명을 자신의 데이터에 맞게 바꿔야 합니다. AI에게 "이 코드가 내 데이터 구조에 맞는지 수정해줘"라고 요청하면 분석 자동화 속도가 크게 올라갑니다.
matplotlib.rcParams['font.family']='Malgun Gothic'(Windows) 또는 'AppleGothic'(Mac)을 설정하세요.데이터 분석의 첫 단계는 원자료가 분석 가능한 상태인지 확인하는 것이다.
import pandas as pd
# 1) CSV 불러오기 (한글 깨짐 시 encoding='cp949' 또는 'utf-8-sig' 시도)
df = pd.read_csv('data.csv')
# 2) 기본 구조 확인
print('행, 열 개수:', df.shape)
print(df.head(10))
print(df.info())
# 3) 결측치 확인
missing = df.isna().sum().sort_values(ascending=False)
missing_rate = (df.isna().mean() * 100).round(2)
print(pd.DataFrame({'결측개수': missing, '결측률(%)': missing_rate}))
# 4) 수치형 변수 요약
print(df.describe())
# 5) 범주형 변수 고유값 확인 (오타 발견용)
for col in df.select_dtypes(include='object').columns:
print(f'\n[{col}] 고유값 {df[col].nunique()}개')
print(df[col].value_counts().head(10))
# 6) 중복 행 확인
print('중복 행 수:', df.duplicated().sum())
조건별 반복 측정값을 평균과 표준편차로 요약하고 그래프로 보여준다.
import pandas as pd
import matplotlib.pyplot as plt
# 예: condition 열에는 조건명, value 열에는 측정값이 있다고 가정
df = pd.read_csv('experiment.csv')
summary = df.groupby('condition')['value'].agg(['count', 'mean', 'std']).reset_index()
summary['se'] = summary['std'] / (summary['count'] ** 0.5) # 표준오차
print(summary)
# 표준편차(SD) 오차막대: 자료 자체의 흩어짐
# 표준오차(SE) 오차막대: 평균 추정의 불확실성
# 그래프 캡션에 어떤 오차인지 반드시 명시할 것
plt.figure(figsize=(8, 5))
plt.bar(summary['condition'], summary['mean'], yerr=summary['std'],
capsize=5, color='#2563eb', alpha=0.7, edgecolor='#0f2454')
plt.xlabel('Condition')
plt.ylabel('Mean value (단위 명시)')
plt.title(f'Mean ± SD by condition (n={summary["count"].iloc[0]})')
plt.tight_layout()
plt.show()
IQR 기준으로 극단값 후보를 찾고, 삭제 전 검토 목록을 만든다.
import pandas as pd
df = pd.read_csv('data.csv')
col = 'value'
# IQR 방식 (분포 가정 없음, 일반적으로 권장)
q1 = df[col].quantile(0.25)
q3 = df[col].quantile(0.75)
iqr = q3 - q1
lower = q1 - 1.5 * iqr
upper = q3 + 1.5 * iqr
outliers = df[(df[col] < lower) | (df[col] > upper)]
print(f'IQR 기준 하한: {lower:.3f}, 상한: {upper:.3f}')
print(f'이상치 후보 수: {len(outliers)} / 전체 {len(df)}')
print(outliers)
# z-score 방식은 정규분포 가정에 가까울 때만 사용
# 치우친 분포에서는 IQR 또는 비율 기준이 더 안전
z_scores = ((df[col] - df[col].mean()) / df[col].std()).abs()
print(f'\nz-score > 3인 행 수: {(z_scores > 3).sum()}')
# 삭제하기 전 확인할 것:
# 1. 측정 당시 장비 오류가 있었는가?
# 2. 단위 입력 오류인가?
# 3. 실제로 의미 있는 특이 사례인가?
# 4. 삭제 전후 결론이 달라지는가? (sensitivity check)
여러 변수 간 관계 후보를 찾고 시각화한다.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# 수치형 열만 선택
df = pd.read_csv('data.csv')
num = df.select_dtypes(include='number')
corr = num.corr()
print(corr.round(3))
# Heatmap: 발산형 색(diverging) 사용 - 양수/음수 상관을 시각적으로 구분
plt.figure(figsize=(8, 6))
plt.imshow(corr, aspect='auto', cmap='RdBu_r', vmin=-1, vmax=1)
plt.colorbar(label='Correlation')
plt.xticks(range(len(corr.columns)), corr.columns, rotation=90)
plt.yticks(range(len(corr.columns)), corr.columns)
# 셀에 값 표시
for i in range(len(corr.columns)):
for j in range(len(corr.columns)):
plt.text(j, i, f'{corr.iloc[i,j]:.2f}', ha='center', va='center',
color='white' if abs(corr.iloc[i,j])>0.5 else 'black', fontsize=8)
plt.title('Correlation matrix')
plt.tight_layout()
plt.show()
# 두 변수 산점도 예시
plt.figure(figsize=(6, 5))
plt.scatter(df['x'], df['y'], alpha=0.6, edgecolor='white')
plt.xlabel('x (단위)')
plt.ylabel('y (단위)')
plt.title(f'Scatter plot (n={len(df)})')
plt.tight_layout()
plt.show()
x가 y를 얼마나 설명하는지 회귀식과 R²로 확인한다.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_absolute_error
df = pd.read_csv('data.csv').dropna(subset=['x', 'y'])
X = df[['x']]
y = df['y']
model = LinearRegression()
model.fit(X, y)
pred = model.predict(X)
print(f'회귀식: y = {model.coef_[0]:.4f} * x + {model.intercept_:.4f}')
print(f'R²: {r2_score(y, pred):.3f}')
print(f'MAE: {mean_absolute_error(y, pred):.3f}')
# 잔차 분석: 패턴이 있으면 선형 가정 위반 가능
residuals = y - pred
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.scatter(df['x'], y, label='data', alpha=0.6)
plt.plot(df['x'], pred, color='red', label='linear fit')
plt.xlabel('x'); plt.ylabel('y'); plt.legend()
plt.title(f'Linear regression (R²={r2_score(y, pred):.3f})')
plt.subplot(1, 2, 2)
plt.scatter(pred, residuals, alpha=0.6)
plt.axhline(0, color='red', linestyle='--')
plt.xlabel('Predicted'); plt.ylabel('Residual')
plt.title('Residual plot (패턴이 없어야 함)')
plt.tight_layout()
plt.show()
여러 변수를 이용해 결과를 예측하고 다중공선성·과적합을 점검한다.
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_absolute_error
df = pd.read_csv('data.csv')
features = ['x1', 'x2', 'x3']
X = df[features]
y = df['target']
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
model = LinearRegression()
model.fit(X_train, y_train)
# 훈련/검증 성능 비교: 격차가 크면 과적합
for name, X_part, y_part in [('train', X_train, y_train), ('test', X_test, y_test)]:
pred = model.predict(X_part)
print(f'{name} R²={r2_score(y_part, pred):.3f} MAE={mean_absolute_error(y_part, pred):.3f}')
# 계수 (영향 크기 순서)
coef = pd.Series(model.coef_, index=features).sort_values(key=abs, ascending=False)
print('\n[계수]\n', coef)
# 다중공선성 확인: VIF가 10 이상이면 변수 간 중복이 심함
# (statsmodels 설치: pip install statsmodels)
try:
from statsmodels.stats.outliers_influence import variance_inflation_factor
vif = pd.DataFrame({
'feature': features,
'VIF': [variance_inflation_factor(X.values, i) for i in range(len(features))]
})
print('\n[VIF] (10 이상이면 다중공선성 의심)\n', vif)
except ImportError:
# statsmodels 없으면 상관행렬로 대체 점검
print('\n[변수 간 상관 (|r|>0.8이면 중복 의심)]')
print(X.corr().round(2))
정상/이상, 성공/실패 같은 분류 문제를 평가한다.
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix, classification_report, ConfusionMatrixDisplay
df = pd.read_csv('classification.csv')
features = ['x1', 'x2', 'x3']
X = df[features]
y = df['label']
# stratify=y : 클래스 비율을 유지하며 분리 (불균형 데이터에 필수)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# class_weight='balanced' : 소수 클래스에 가중치
model = RandomForestClassifier(random_state=42, class_weight='balanced', n_estimators=100)
model.fit(X_train, y_train)
pred = model.predict(X_test)
print('=== 혼동행렬 ===')
print(confusion_matrix(y_test, pred))
print('\n=== 분류 리포트 ===')
print(classification_report(y_test, pred))
# 시각화
ConfusionMatrixDisplay.from_predictions(y_test, pred, cmap='Blues')
plt.title('Confusion Matrix')
plt.tight_layout()
plt.show()
# 변수 중요도 (예측 기여도 - 인과 효과 아님!)
importance = pd.Series(model.feature_importances_, index=features).sort_values()
plt.figure(figsize=(7, 4))
importance.plot(kind='barh', color='#06b6d4')
plt.xlabel('Importance (예측 기여도)')
plt.title('Feature importance')
plt.tight_layout()
plt.show()
라벨 없는 데이터를 비슷한 유형으로 묶고 2차원으로 시각화한다.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
df = pd.read_csv('data.csv')
features = ['x1', 'x2', 'x3', 'x4']
X = df[features].dropna()
# 표준화: 단위가 다른 변수를 동등하게 비교
X_scaled = StandardScaler().fit_transform(X)
# Elbow method: 적절한 k 찾기
inertias = []
ks = range(2, 8)
for k in ks:
km = KMeans(n_clusters=k, random_state=42, n_init=10)
km.fit(X_scaled)
inertias.append(km.inertia_)
plt.figure(figsize=(6, 4))
plt.plot(ks, inertias, 'o-', color='#2563eb')
plt.xlabel('Number of clusters (k)')
plt.ylabel('Inertia (within-cluster sum of squares)')
plt.title('Elbow method')
plt.tight_layout()
plt.show()
# 최종 모델 (예시: k=3, elbow 결과 보고 조정)
k = 3
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
clusters = kmeans.fit_predict(X_scaled)
X['cluster'] = clusters
# PCA로 2차원 시각화 (군집별 색 구분 + 범례)
pca = PCA(n_components=2)
XY = pca.fit_transform(X_scaled)
plt.figure(figsize=(7, 5))
colors = ['#2563eb', '#10b981', '#f59e0b', '#7c3aed', '#ef4444', '#06b6d4']
for c in range(k):
mask = clusters == c
plt.scatter(XY[mask, 0], XY[mask, 1], c=colors[c], label=f'Cluster {c}',
alpha=0.7, edgecolor='white', s=50)
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]*100:.1f}%)')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]*100:.1f}%)')
plt.title(f'K-means clusters (k={k}) projected by PCA')
plt.legend()
plt.tight_layout()
plt.show()
# 군집별 프로파일: 각 군집의 평균값으로 이름 붙이기
print('=== 군집별 평균값 (원자료 단위) ===')
print(X.groupby('cluster')[features].mean().round(3))
센서 로그에서 큰 흐름과 비정상 구간을 찾는다. 전체 평균이 아닌 이동 통계 기반으로 이상 구간을 탐지한다.
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('sensor.csv')
df['time'] = pd.to_datetime(df['time'])
df = df.sort_values('time').reset_index(drop=True)
col = 'value'
window = 12 # 이동 창 크기 (데이터 간격에 맞게 조정)
# 이동평균과 이동표준편차 (rolling): 시계열 추세를 반영한 이상 탐지
df['moving_avg'] = df[col].rolling(window=window, min_periods=1, center=True).mean()
df['moving_std'] = df[col].rolling(window=window, min_periods=1, center=True).std()
# 이상 구간: 이동평균 ± 3 * 이동표준편차 범위를 벗어난 점
df['upper'] = df['moving_avg'] + 3 * df['moving_std']
df['lower'] = df['moving_avg'] - 3 * df['moving_std']
df['anomaly'] = (df[col] > df['upper']) | (df[col] < df['lower'])
print(f'전체 {len(df)}개 중 이상 후보: {df["anomaly"].sum()}개')
plt.figure(figsize=(12, 5))
plt.plot(df['time'], df[col], label='raw', color='#cbd5e1', linewidth=0.8)
plt.plot(df['time'], df['moving_avg'], label='moving average', color='#2563eb', linewidth=2)
plt.fill_between(df['time'], df['lower'], df['upper'], alpha=0.15, color='#2563eb', label='±3 SD band')
plt.scatter(df.loc[df['anomaly'], 'time'], df.loc[df['anomaly'], col],
color='#ef4444', label='anomaly', zorder=5, s=40)
plt.xlabel('Time')
plt.ylabel(col)
plt.title(f'Rolling mean anomaly detection (window={window})')
plt.legend()
plt.tight_layout()
plt.show()
# 이상으로 표시된 점이 정말 이상인지 원자료와 측정 로그를 직접 확인할 것
# 센서 고장, 정상 변동, 진짜 이상사건을 구분하는 것은 사람의 몫
한국어는 조사가 단어에 붙어 단순 split이 부정확하다. 형태소 분석 라이브러리(KoNLPy 등)를 권장한다.
from collections import Counter
import pandas as pd
import matplotlib.pyplot as plt
import re
df = pd.read_csv('text.csv')
texts = df['text'].dropna().astype(str)
# ====== 방법 A: 라이브러리 없이 간단 처리 (영문/단순 한글) ======
# - 빠르지만 한국어 조사가 단어에 붙어 나옴 ("학교는", "학교를"이 다른 단어로 카운트됨)
stopwords = {'그리고','하지만','또한','대한','관련','으로','에서','이다','있다','이다','하는',
'이런','그런','저런','우리','저희','때문','정도','이번','다음','경우'}
words = []
for text in texts:
# 특수문자 제거
cleaned = re.sub(r'[^\w\s가-힣]', ' ', text)
for w in cleaned.split():
w = w.strip()
if len(w) >= 2 and w not in stopwords:
words.append(w)
counter = Counter(words)
top = pd.DataFrame(counter.most_common(20), columns=['word', 'count'])
print(top)
plt.figure(figsize=(9, 5))
plt.barh(top['word'][::-1], top['count'][::-1], color='#2563eb')
plt.xlabel('Count')
plt.title('Top 20 keywords (간단 처리)')
plt.tight_layout()
plt.show()
# ====== 방법 B: KoNLPy로 명사만 추출 (정확하지만 설치 필요) ======
# pip install konlpy (Mac/Linux는 Java 설치 필요)
# from konlpy.tag import Okt
# okt = Okt()
# nouns = []
# for text in texts:
# for n in okt.nouns(text):
# if len(n) >= 2 and n not in stopwords:
# nouns.append(n)
# Counter(nouns).most_common(20)
# ====== 방법 C: 형태소 분석 없이도 정확도를 올리는 방법 ======
# - 조사 목록을 만들어 단어 끝에서 제거
# - 자주 등장하는 어미("입니다", "합니다") 제외
# - 길이 3자 이상만 유지
여러 문서에서 각 문서를 구분하는 특징 단어를 찾는다.
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
df = pd.read_csv('documents.csv')
texts = df['text'].fillna('').astype(str).tolist()
# 한국어는 token_pattern을 한글 포함으로 설정
vectorizer = TfidfVectorizer(
max_features=1000,
token_pattern=r'(?u)\b[\w가-힣]{2,}\b',
min_df=2 # 최소 2개 문서에 등장한 단어만
)
X = vectorizer.fit_transform(texts)
terms = vectorizer.get_feature_names_out()
# 각 문서별 특징어 상위 10개
for doc_idx in range(min(5, len(texts))): # 처음 5개 문서만 출력
row = X[doc_idx].toarray().ravel()
top_idx = row.argsort()[-10:][::-1]
print(f'\n[문서 {doc_idx}] 특징어:')
for i in top_idx:
if row[i] > 0:
print(f' {terms[i]}: {row[i]:.3f}')
사진의 색상 변화를 숫자로 바꿔 조건별로 비교한다.
# pip install Pillow numpy pandas
from PIL import Image
import numpy as np
import pandas as pd
from pathlib import Path
records = []
image_folder = Path('images')
for file in sorted(image_folder.glob('*.jpg')):
img = Image.open(file).convert('RGB')
arr = np.array(img)
mean_rgb = arr.reshape(-1, 3).mean(axis=0)
brightness = arr.mean() # 전체 픽셀 평균 밝기
# HSV로 변환해 색조(Hue) 평균도 함께 추출
hsv = np.array(img.convert('HSV'))
hue_mean = hsv[..., 0].mean()
records.append({
'file': file.name,
'R_mean': round(mean_rgb[0], 2),
'G_mean': round(mean_rgb[1], 2),
'B_mean': round(mean_rgb[2], 2),
'brightness': round(brightness, 2),
'hue_mean': round(hue_mean, 2)
})
result = pd.DataFrame(records)
print(result)
result.to_csv('image_color_summary.csv', index=False, encoding='utf-8-sig')
# 주의: 촬영 조명·각도·거리·배경이 달라지면 색 변화가 왜곡됨
# - 같은 조명, 같은 거리, 같은 배경으로 촬영
# - 색 표준카드(컬러체커)나 흰색 기준판을 함께 촬영해 보정
측정 오차가 결과에 미치는 영향을 확률적으로 확인한다.
import numpy as np
import matplotlib.pyplot as plt
# 재현성: 같은 seed로 결과 고정
rng = np.random.default_rng(seed=42)
# 예: 밀도 = 질량 / 부피
# 질량은 평균 10.0g, 표준편차 0.2g / 부피는 평균 5.0mL, 표준편차 0.1mL라고 가정
n = 10000
mass = rng.normal(loc=10.0, scale=0.2, size=n)
volume = rng.normal(loc=5.0, scale=0.1, size=n)
density = mass / volume
p025, p975 = np.percentile(density, [2.5, 97.5])
print(f'평균 밀도: {density.mean():.4f} g/mL')
print(f'표준편차: {density.std():.4f}')
print(f'95% 범위: [{p025:.4f}, {p975:.4f}]')
print(f'특정 기준(2.05 g/mL) 초과 확률: {(density > 2.05).mean()*100:.2f}%')
plt.figure(figsize=(8, 5))
plt.hist(density, bins=50, color='#2563eb', alpha=0.7, edgecolor='white')
plt.axvline(density.mean(), color='red', linestyle='--', label=f'mean={density.mean():.3f}')
plt.axvline(p025, color='orange', linestyle=':', label=f'95% CI')
plt.axvline(p975, color='orange', linestyle=':')
plt.xlabel('Density (g/mL)')
plt.ylabel('Frequency')
plt.title(f'Monte Carlo simulation (n={n})')
plt.legend()
plt.tight_layout()
plt.show()
# 주의: 입력 분포 가정(여기서는 정규분포)이 틀리면 결과도 틀림
# - 실제 측정값으로 분포 확인 후 가정 변경 가능 (균등, 삼각, 로그정규 등)
AI가 한 일과 학생이 검증한 일을 분리해 기록한다.
import pandas as pd
from datetime import datetime
# 분석 과정에서 한 줄씩 추가
log = pd.DataFrame([
{
'date': '2026-05-14',
'step': 1,
'purpose': '결측치 점검 코드 작성',
'ai_model': 'ChatGPT-4',
'prompt_summary': '결측률 계산 pandas 코드 요청',
'ai_suggestion': 'isna().sum(), 결측률 계산 코드 제안',
'my_verification': '원자료 3개 행을 직접 확인해 실제 결측과 일치하는지 검토',
'revision': '측정 불가로 기록된 NA는 삭제하지 않고 별도 범주로 유지',
'used_in_report': 'yes'
},
{
'date': '2026-05-15',
'step': 2,
'purpose': '회귀분석 코드 검증',
'ai_model': 'Claude',
'prompt_summary': '회귀 결과 해석 요청',
'ai_suggestion': 'R²=0.72라서 강한 관계라고 해석',
'my_verification': '잔차에 곡선 패턴 발견, 선형 가정 위반 가능성 확인',
'revision': '2차 다항회귀로 변경, 해석을 "관계"로 표현',
'used_in_report': 'yes'
}
])
log.to_csv('ai_usage_log.csv', index=False, encoding='utf-8-sig')
print(log[['date', 'step', 'purpose', 'used_in_report']])
# 보고서에 첨부할 수 있도록 마크다운으로도 출력
print('\n=== 보고서용 요약 ===')
for _, row in log.iterrows():
print(f"- [{row['date']}] {row['purpose']}")
print(f" · AI 제안: {row['ai_suggestion']}")
print(f" · 내 검증: {row['my_verification']}")
print(f" · 수정: {row['revision']}")
좋은 프롬프트는 “분석해줘”가 아니라, 데이터의 맥락·열 구조·분석 목표·검증 기준·출력 형식을 함께 제시하는 분석 명세서입니다. 아래 템플릿은 실제 데이터를 붙여 넣고 바로 수정해 사용할 수 있도록 구체적으로 구성했습니다.
AI에게 분석을 맡길수록 학생이 제공해야 할 정보는 더 구체적이어야 합니다.
“이 CSV 분석해줘.”
“그래프 그려줘.”
“머신러닝 해줘.”
“열 이름과 샘플 10행을 보고 단위·결측·이상치를 점검한 뒤, 조건별 평균 비교와 오차막대 그래프를 그리는 pandas 코드를 작성해줘. 결과 해석은 인과가 아니라 경향으로 표현해줘.”
데이터 유형과 분석 목표를 입력하면, AI에게 바로 보낼 수 있는 분석 요청문을 자동으로 구성합니다.
AI를 활용할수록 결과가 그럴듯해 보이기 때문에, 오류를 찾는 루틴이 더 중요합니다.
정답을 알 수 있는 미래 정보가 입력 변수에 들어가 성능이 비정상적으로 높아지는 오류입니다. 예: 시계열을 무작위 셔플하기, 결과값에서 만든 파생변수 포함.
상관분석이나 회귀분석 결과를 "원인"으로 단정하지 말고 관계·경향·가능성으로 표현합니다. 관찰 데이터로는 인과를 입증하기 어렵습니다.
훈련 데이터에서는 잘 맞지만 새 데이터에서는 실패하는 모델입니다. 훈련/검증 점수 차이가 크면 의심합니다. 검증 분리와 교차검증이 필요합니다.
mg/L, ppm, ℃, K, 시간 단위가 섞이면 그래프와 모델이 모두 틀어집니다. 분석 전 단위 통일 점검표를 만드세요.
정상 데이터가 대부분이면 정확도 95% 모델도 이상을 전혀 못 찾을 수 있습니다. 정밀도·재현율·F1을 함께 보세요.
축 범위 조작, 부적절한 로그 스케일, 표본 수 누락, 오차막대 생략은 결론을 과장할 수 있습니다.
AI가 없는 라이브러리, 틀린 통계 개념, 존재하지 않는 함수·논문·출처를 자신 있게 제안할 수 있습니다. 코드는 반드시 실행해 검증하세요.
공공데이터, 이미지, 논문, 기사 자료는 출처와 이용 조건을 확인해야 합니다. 무단 사용은 표절·저작권 침해가 됩니다.
설문, 위치, 건강, 성적 관련 데이터는 익명화하고 민감정보를 AI에 직접 입력하지 않습니다. 이름·학번·연락처는 분석 전 마스킹합니다.
실제 데이터로 분석을 시작할 때 참고할 수 있는 한국·해외 데이터 포털입니다. 모든 데이터는 이용 조건과 저작권을 확인한 뒤 사용하세요.
중앙·지방·공공기관 데이터의 통합 창구. 기상, 교통, 환경, 보건, 교육 등 광범위한 분야의 CSV·API 제공.
인구·가구·경제·사회 통계의 공식 출처. 시계열·지역별 비교 데이터에 강점.
기상청의 관측·예보 데이터. 기온·강수·풍속·미세먼지 시계열 분석에 적합.
전국 대기질 측정망 데이터. 미세먼지·오존·CO·NO₂ 등 시간별 측정값.
서울시 행정·교통·관광·환경 데이터. 지역 단위 탐구에 유용. 다른 광역시도 비슷한 포털 운영.
국내 학술논문·학위논문·연구보고서 검색. 선행연구 정리에 활용.
전 세계 사용자 공유 데이터셋과 노트북. 머신러닝 연습용 데이터가 풍부.
오래 검증된 머신러닝용 데이터셋 모음. 분류·회귀·군집 학습용으로 적합.
인구·환경·보건·교육·경제의 국가 비교 데이터와 시각화. CSV 다운로드 제공.
위성 관측, 기후, 해양 데이터. 환경·기후 탐구에 활용 가능.
유전자, 단백질, 생명정보 공개 데이터. 생명과학 탐구에 활용.
한국어 자연어 처리용 말뭉치. 텍스트 분석 학습에 활용.
대화형 AI마다 강점이 조금씩 다릅니다. 도구를 바꿔보고 결과를 비교하는 것도 중요한 검증 방법입니다.
분석 설계, 코드 초안, 결과 해석 문장 작성에 강점. 파일 업로드와 코드 실행을 지원하는 버전은 데이터 자체를 분석할 수도 있습니다.
AI가 만든 Python 코드를 바로 실행해 결과를 확인할 수 있는 무료 클라우드 노트북. GPU도 일부 제공됩니다.
코드 없이도 가능한 기초 분석 도구. AI 챗봇과 함께 쓰면 수식·피벗 사용법을 빠르게 익힐 수 있습니다.
분석 결과를 발표용 그래프로 만드는 도구. matplotlib은 기본기에, Plotly는 인터랙티브에, Tableau Public은 대시보드에 강점.
이미지 분석 전문 도구. ImageJ는 GUI 기반으로 시작이 쉽고, OpenCV는 Python에서 정교한 처리가 가능.
설문 데이터 수집과 CSV 내보내기. AI에게 설문 문항 검토와 응답 분석 코드까지 요청할 수 있습니다.
기술적으로 가능하다는 것과 윤리적으로 정당하다는 것은 다릅니다. 보고서·논문·발표에 AI를 사용했다면 그 사실을 명시하는 것이 학술 정직성의 출발점입니다.
이름, 학번, 전화번호, 주소, 건강 정보, 가족 사항, 정확한 위치 등은 AI에 직접 입력하지 않습니다. 분석 전 단계에서 익명화·마스킹·집계 처리합니다.
공공데이터, 논문, 이미지, 기사, 코드, AI 생성물 모두 출처와 라이선스를 확인합니다. CC-BY는 출처 표기 시 사용 가능, CC-NC는 비영리 한정, All Rights Reserved는 별도 허락 필요.
AI를 사용했다는 사실을 보고서·발표 자료에 명확히 적습니다. 어떤 부분에서 어떤 모델을 어떻게 사용했고, 학생이 어떻게 검증·수정했는지 함께 기록하면 표절 논란을 피할 수 있습니다.
불리한 이상치를 임의로 삭제하거나 결과를 미리 정해놓고 분석하지 않습니다. 모든 전처리 결정은 측정 맥락과 사전 기준으로 정당화되어야 합니다.
실제 데이터가 보여준 것보다 더 강하게 해석하지 않습니다. "원인이다"보다 "관계가 관찰되었다", "증명되었다"보다 "지지하는 결과가 나왔다"가 정확합니다.
친구·가족·학우를 대상으로 한 설문이나 측정은 사전에 연구 목적·익명성·중단 권리를 알리고 동의를 받습니다. 미성년자나 민감 주제는 보호자·교사와 상의합니다.
분석을 시작하기 전에 아래 항목을 채우면, AI에게 보낼 수 있는 분석 계획 프롬프트와 기록 양식이 만들어집니다.
고등학생들이 AI로 데이터 분석을 시작할 때 가장 많이 던지는 질문과 답변을 모았습니다.