Pandas
pandas is an open source, BSD-licensed library providing high-performance, easy-to-use data structures and data analysis tools for the Python programming language.
Categories
Examples
- PlcGateway#pandas 패킷 로그 통계 - wireshark 로그를 분석하여 (근데 결국 text 분석임) 통계
데이터 순회 방법
DataFrame의 행(row)과 열(column)을 순회하는 여러 가지 방법을 알려드리겠습니다
import pandas as pd
# 예시 데이터프레임
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
# 1. 행(row) 순회하기
# 1.1 iterrows() - index와 Series 반환
for index, row in df.iterrows():
print(f"Index: {index}")
print(f"Row: {row['A']}, {row['B']}, {row['C']}")
# 1.2 itertuples() - 각 행을 named tuple로 반환 (더 빠름)
for row in df.itertuples():
print(f"Index: {row.Index}")
print(f"Values: {row.A}, {row.B}, {row.C}")
# 1.3 index를 사용한 순회
for idx in range(len(df)):
row = df.iloc[idx]
print(f"Row {idx}: {row['A']}, {row['B']}, {row['C']}")
# 2. 열(column) 순회하기
# 2.1 기본 열 순회
for col in df.columns:
print(f"Column {col}:")
print(df[col].values)
# 2.2 items()를 사용한 열 순회 - (열 이름, Series) 반환
for col_name, col_data in df.items():
print(f"Column {col_name}:")
print(col_data.values)
# 3. 전체 셀 순회하기
# 3.1 이중 루프 사용
for i in range(len(df)):
for col in df.columns:
value = df.iloc[i][col]
print(f"Row {i}, Col {col}: {value}")
# 3.2 numpy array로 변환 후 순회
for i in range(df.shape[0]):
for j in range(df.shape[1]):
value = df.iloc[i, j]
print(f"Row {i}, Col {df.columns[j]}: {value}")
각 방법의 특징과 사용 시 참고사항:
- 행(row) 순회:
-
iterrows()
: 가장 직관적이지만 상대적으로 느림 -
itertuples()
: 가장 빠른 방법, 특히 큰 데이터프레임에 추천 -
iloc[]
: 인덱스 기반 접근이 필요할 때 유용
-
- 열(column) 순회:
-
columns
속성 사용: 간단하고 직관적 -
items()
: 열 이름과 데이터를 함께 처리할 때 유용
-
- 성능 고려사항:
- 큰 데이터의 경우 itertuples()가 가장 빠름
- 가능하면 벡터화된 연산 사용을 권장 (for loop 대신)
- numpy 배열로 변환 후 처리하면 더 빠를 수 있음
column 추가 방법
DataFrame에 새로운 column을 추가하는 다양한 방법을 알려드리겠습니다:
import pandas as pd
# 예시 데이터프레임
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
# 1. 직접 할당
# 1.1 단일 값 할당
df['C'] = 10 # 모든 행에 동일한 값 할당
# 1.2 리스트나 배열 할당
df['D'] = [7, 8, 9] # 각 행마다 다른 값 할당
# 1.3 다른 컬럼을 기반으로 계산
df['E'] = df['A'] + df['B'] # 컬럼 A와 B의 합
# 2. insert() 메서드 사용 - 특정 위치에 삽입
df.insert(loc=1, column='F', value=[10, 11, 12])
# 3. assign() 메서드 사용 - 체이닝 가능
df = df.assign(G=lambda x: x['A'] * 2,
H=lambda x: x['B'] + 5)
# 4. 조건문으로 새 컬럼 생성
df['I'] = df['A'].apply(lambda x: 'High' if x > 2 else 'Low')
# 5. 여러 컬럼 한번에 추가
new_cols = {
'J': [13, 14, 15],
'K': [16, 17, 18]
}
df = pd.concat([df, pd.DataFrame(new_cols)], axis=1)
# 6. apply 함수로 복잡한 계산 후 추가
df['L'] = df.apply(lambda row: row['A'] * row['B'] + 2, axis=1)
# 7. 기존 컬럼 복사
df['M'] = df['A'].copy()
# 8. where 조건으로 추가
df['N'] = df['A'].where(df['A'] > 2, df['B'])
# 9. cut/qcut으로 범주형 컬럼 추가
df['O'] = pd.cut(df['A'], bins=2, labels=['Low', 'High'])
각 방법의 특징과 사용 시 참고사항:
- 직접 할당
(df['new_col'] = value)
- 가장 간단하고 직관적인 방법
- 단일 값, 리스트, 시리즈 모두 할당 가능
insert()
메서드- 특정 위치에 컬럼을 삽입할 때 유용
- loc: 삽입할 위치 인덱스
- column: 새 컬럼 이름
- value: 컬럼에 들어갈 값
assign()
메서드- 메서드 체이닝에 적합
- 원본 데이터프레임 변경 없이 새로운 데이터프레임 반환
- lambda 함수 사용 가능
데이터 타입 관련 주의사항:
# 데이터 타입 지정하여 컬럼 추가
df['P'] = pd.Series([1, 2, 3], dtype='int32')
# 날짜 컬럼 추가
df['date'] = pd.date_range('2024-01-01', periods=len(df))
# 범주형(categorical) 컬럼 추가
df['category'] = pd.Categorical(['A', 'B', 'C'])
성능 최적화:
# 대용량 데이터의 경우 벡터화 연산 사용 권장
# Bad (느림):
df['new_col'] = df.apply(lambda row: row['A'] + row['B'], axis=1)
# Good (빠름):
df['new_col'] = df['A'] + df['B']
이러한 방법들 중에서 상황에 맞는 가장 적절한 방법을 선택하시면 됩니다. 일반적으로 간단한 연산은 직접 할당이, 복잡한 연산은 assign()
이나 apply()
메서드가 유용합니다.
순회중인 row 에 column 추가 방법
DataFrame을 순회하면서 각 행(row)에 새로운 계산 결과를 추가하는 방법을 알려드리겠습니다:
import pandas as pd
# 예시 데이터프레임
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
# 1. iterrows() 사용 - 새 컬럼을 미리 만들고 값 할당
df['C'] = None # 또는 df['C'] = 0
for idx, row in df.iterrows():
# 현재 행의 값들을 이용해 계산
result = row['A'] * row['B']
df.at[idx, 'C'] = result
# 2. apply() 사용 (더 효율적)
def process_row(row):
row['C'] = row['A'] * row['B']
return row
df = df.apply(process_row, axis=1)
# 3. 여러 컬럼 한번에 추가
df[['C', 'D']] = None # 먼저 빈 컬럼 생성
for idx, row in df.iterrows():
df.at[idx, 'C'] = row['A'] * 2
df.at[idx, 'D'] = row['B'] + 5
# 4. loc 사용
for idx in df.index:
df.loc[idx, 'E'] = df.loc[idx, 'A'] + df.loc[idx, 'B']
# 5. 복잡한 조건부 계산
df['F'] = None
for idx, row in df.iterrows():
if row['A'] > 2:
df.at[idx, 'F'] = row['A'] * row['B']
else:
df.at[idx, 'F'] = row['A'] + row['B']
대부분의 경우, 가능하다면 벡터화된 연산을 사용하는 것이 좋습니다.
성능 최적화
# 비효율적인 방법
for idx, row in df.iterrows():
df.loc[idx, 'new_col'] = row['A'] * 2 # 느림
# 효율적인 방법 1: at 사용
for idx, row in df.iterrows():
df.at[idx, 'new_col'] = row['A'] * 2 # 더 빠름
# 효율적인 방법 2: 벡터화 연산
df['new_col'] = df['A'] * 2 # 가장 빠름
메모리 효율성을 위한 방법
# 큰 데이터셋의 경우
chunk_size = 1000
for i in range(0, len(df), chunk_size):
chunk = df.iloc[i:i + chunk_size]
for idx, row in chunk.iterrows():
df.at[idx, 'new_col'] = row['A'] * 2
여러 컬럼을 동시에 업데이트
# 효율적인 방법
for idx, row in df.iterrows():
updates = {
'C': row['A'] * 2,
'D': row['B'] + 5,
'E': row['A'] + row['B']
}
for col, value in updates.items():
df.at[idx, col] = value
조건부 로직이 있는 경우
def calculate_value(row):
if row['A'] > 2:
return row['A'] * row['B']
elif row['B'] < 5:
return row['A'] + row['B']
else:
return 0
# 방법 1: apply 사용
df['result'] = df.apply(calculate_value, axis=1)
# 방법 2: iterrows 사용
df['result'] = None
for idx, row in df.iterrows():
df.at[idx, 'result'] = calculate_value(row)
에러 처리
df['result'] = None
for idx, row in df.iterrows():
try:
df.at[idx, 'result'] = complex_calculation(row)
except Exception as e:
print(f"Error at index {idx}: {e}")
df.at[idx, 'result'] = None # 또는 다른 기본값
Insert a row
몇 가지 답변을 테스트해 보면 pd.concat()
을 사용하는 것이 대규모 데이터 프레임에 더 효율적이라는 것이 분명합니다.
인자로 ignore_index=True
를 사용하는 이유는 pandas에서 데이터를 병합하거나 행을 추가할 때 인덱스를 무시하고 새로운 연속된 인덱스를 생성하도록 하는 옵션입니다.
예를 들어, DataFrame을 concat하거나 reset_index
할 때 ignore_index=True
를 설정하면 기존 인덱스를 무시하고 0부터 시작하는 새로운 인덱스를 지정합니다.
이는 데이터 프레임을 이어 붙이거나 인덱스를 재설정할 때 기존의 인덱스를 유지할 필요가 없는 경우 유용합니다.
pd.concat() + list
df = pd.DataFrame(columns=['a', 'b'])
for i in range(10000):
df = pd.concat([pd.DataFrame([[1,2]], columns=df.columns), df], ignore_index=True)
4.88 s ± 47.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
pd.append() + dict [removed as of v2.0.0]
df = pd.DataFrame(columns=['a', 'b'])
for i in range(10000):
df = df.append({'a': 1, 'b': 2}, ignore_index=True)
10.2 s ± 41.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
pd.DataFrame().loc + index operations
df = pd.DataFrame(columns=['a','b'])
for i in range(10000):
df.loc[-1] = [1,2]
df.index = df.index + 1
df = df.sort_index()
17.5 s ± 37.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
또 다른 concat 예제
import pandas as pd
import numpy as np
df1 = pd.DataFrame(np.array([[2, 3, 4]]), columns=['A', 'B', 'C'])
df2 = pd.DataFrame(np.array([[5, 6, 7]]), columns=df.columns)
df3 = pd.concat([df1, df2], ignore_index=True)
print(df3)
CSV 사용하기 예제
import pandas as pd
import glob
# csv 파일들 목록
files = glob.glob("*.csv")
# csv 파일들 읽기
dfs = [pd.read_csv(f, encoding="cp949") for f in files]
# 모든 데이터 프레임(DataFrame) 병합
# `ignore_index=True`를 설정하면 dfs의 모든 DataFrame 인덱스를 무시하고 0부터 시작하는 연속된 인덱스를 생성합니다.
df = pd.concat(dfs, ignore_index=True)
# idx 기준으로 재 정렬
sorted_df = df.sort_values(by="idx", ascending=True)
# 결과 저장
sorted_df.to_csv("sorted_df.csv", index=False)
SQLite3 읽기
import sqlite3
import pandas as pd
with sqlite3.connect("database.sqlite") as conn:
query = "select * from my_table where value <= 0"
df = pd.read_sql_query(query, conn)
print(df)
데이터 타입 지정 방법
특정 열(Column)에서 데이터 타입이 혼합된 경우 이를 해결하기 위해 몇 가지 방법이 있습니다.
dtype 옵션 지정하기
CSV 파일을 읽을 때 dtype
인자를 사용하여 데이터 타입을 명시적으로 설정합니다. 예를 들어:
column_name
은 문제가 발생한 열의 이름입니다. 이 경우 문자열로 지정했지만 데이터에 따라 적합한 타입으로 변경하면 됩니다.
전체 파일을 한 번에 읽어 분석
Pandas는 기본적으로 메모리를 절약하기 위해 CSV 파일을 청크로 읽습니다. low_memory=False
를 설정하면 전체 파일을 한 번에 읽어 분석하므로 경고를 방지할 수 있습니다.
문제가 되는 열 조사 및 데이터 타입 통일하기
CSV 파일의 5번째 열(Column 5)이 문제라면 해당 열 데이터를 조사하여 데이터 타입을 통일하는 것이 좋습니다.
출력된 타입을 확인한 후, 데이터를 변환하거나 수정할 수 있습니다:
CSV 파일 사전 처리하기
CSV 파일 자체를 수정하여 문제를 해결할 수도 있습니다. 예를 들어, Excel에서 문제 열의 데이터 형식을 통일한 후 다시 저장합니다.
Excel 하나의 파일, 여러 시트로 DataFrame 쓰기
import pandas as pd
import sqlite3
# A.sqlite 처리
with open("2410_report.sql", "r", encoding="utf-8") as file:
sql_query = file.read()
# A.sqlite 연결 및 데이터 읽기
conn_a = sqlite3.connect("A.sqlite")
df_a = pd.read_sql_query(sql_query, conn_a)
conn_a.close()
# B.sqlite 연결 및 데이터 읽기
conn_b = sqlite3.connect("B.sqlite")
df_b = pd.read_sql_query(sql_query, conn_b)
conn_b.close()
# Excel에 쓰기 (두 시트를 각각 저장)
output_excel = "output.xlsx"
with pd.ExcelWriter(output_excel, engine="openpyxl") as writer:
df_a.to_excel(writer, sheet_name="A", index=False)
df_b.to_excel(writer, sheet_name="B", index=False)
print(f"데이터가 {output_excel} 파일로 저장되었습니다. (A 시트: A.sqlite, B 시트: B.sqlite)")
openpyxl 로 이미 열어놓은 Workbook 있음. 여기에 pandas 로 쓰기
import pandas as pd
from openpyxl import Workbook
# 이미 열려 있는 Workbook 가정
wb = Workbook() # 또는 openpyxl.load_workbook()으로 기존 파일 불러오기
ws = wb.active # 활성화된 Sheet 선택
# Pandas DataFrame 생성
data = {
"Name": ["Alice", "Bob", "Charlie"],
"Age": [25, 30, 35],
"City": ["New York", "Los Angeles", "Chicago"]
}
df = pd.DataFrame(data)
# DataFrame 데이터를 openpyxl Worksheet에 쓰기
for r_idx, row in enumerate(df.itertuples(index=False), start=1):
for c_idx, value in enumerate(row, start=1):
ws.cell(row=r_idx, column=c_idx, value=value)
# 저장하거나 작업 계속 진행
wb.save("example.xlsx") # 저장 (필요 시)
직접 Excel Cell 에 추가하는 방법
# 헤더 추가
for c_idx, column in enumerate(df.columns, start=1):
ws.cell(row=1, column=c_idx, value=column)
# 데이터 추가 (헤더 아래부터 시작)
for r_idx, row in enumerate(df.itertuples(index=False), start=2):
for c_idx, value in enumerate(row, start=1):
ws.cell(row=r_idx, column=c_idx, value=value)
openpyxl 의 WorkSheet 에 추가하는 방법
from openpyxl import Workbook
from openpyxl.utils.dataframe import dataframe_to_rows
import pandas as pd
# 샘플 DataFrame 생성
data = {
"Name": ["Alice", "Bob", "Charlie"],
"Age": [25, 30, 35],
"City": ["New York", "Los Angeles", "Chicago"]
}
df = pd.DataFrame(data)
# Workbook 및 Worksheet 생성
wb = Workbook()
ws = wb.active
ws.title = "Sample Data"
# DataFrame 데이터를 Worksheet에 쓰기
# header=True: 컬럼명을 포함
# index=False: 인덱스를 포함하지 않음
for row in dataframe_to_rows(df, index=False, header=True):
ws.append(row)
# 엑셀 파일 저장
wb.save("example.xlsx")
두 개의 DataFrame 병합 방법
import pandas as pd
# 데이터 읽기
df = pd.read_excel("data.xlsx")
# 상부와 측면 쌍으로 병합
df_upper = df[df['Column7'] == '상부']
df_side = df[df['Column7'] == '측면']
# Key 열 기준으로 병합
merged_df = pd.merge(df_upper, df_side, on=['Column1', 'Column2', 'Column3'], suffixes=('_상부', '_측면'))
# 결과 저장
merged_df.to_excel("merged_data.xlsx", index=False)
DataFrame 의 특정 col 데이터는 모두 특정 함수에 넣은 결과로 대체하는 방법
import pandas as pd
# 예제 DataFrame
data = {'col1': [1, 2, 3], 'col2': ['a', 'b', 'c']}
df = pd.DataFrame(data)
# 사용자 정의 함수
def my_text_append(val):
return f"Appended_{val}"
# 특정 열(col2)의 데이터를 함수 결과로 대체
df['col2'] = df['col2'].apply(my_text_append)
print(df)
정렬 방법
# idx 기준으로 재 정렬
sorted_df = df.sort_values(by="idx", ascending=True)
# "UP_WORK_DT", "WORK_SEQ" 두 개의 기준으로 재 정렬
self._df = self._df.sort_values(by=["UP_WORK_DT", "WORK_SEQ"], ascending=True)
주의할 점은 위와 같이 재정렬하면 index는 기존 index로 유지되므로 (필요시) 리셋해줘야한다.
특정 컬럼의 동일 값을 그룹으로 묶기
숫자가 증가하다가 초기화 되는 타이밍에 맞춰 그룹 Index 지정한 후 Column 추가
이런식으로 1씩 증가하다 특정 타이밍에 1로 초기화될 때 맞춰서 초기화 되는 Column 이 있다면
증가되는 부분 까지 같은 그룹 Index 로 묶는 방법
import pandas as pd
# 예제 데이터 생성
data = {
"장입순서": [1] * 28 + [2] * 7,
"그라플순서": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1, 2, 3, 4, 5, 6, 7],
}
df = pd.DataFrame(data)
# "그라플순서"가 초기화되는 순간을 감지
df['그라플그룹'] = (df['그라플순서'] < df['그라플순서'].shift(1)).cumsum() + 1
print(df)
-
shift(1)
- 이전 행의 값을 가져옵니다.- 이를 통해 현재 행의 "그라플순서"가 이전 값보다 작은지를 확인합니다.
<
연산 - "그라플순서"가 이전 값보다 작다면 True를 반환합니다. cumsum()
- True 값을 누적하여 그룹 번호를 만듭니다. +1
- 그룹 번호를 1부터 시작하도록 설정합니다. 이 방식으로 각 "그라플순서"가 초기화되는 순간을 기반으로 새로운 그룹 번호를 추가할 수 있습니다.
순서(Index)를 별도의 컬럼에 그대로 저장하는 방법
간단하게 현재 index를 새로운 컬럼으로 복사. 기존 index는 그대로 유지됨.
index를 'ORI_IDX' 컬럼으로 변환. 새로운 숫자 index(0부터 시작)가 생성됨. 더 공식적인 방법.
출력 옵션 임시 변경
import pandas as pd
# ...
with pd.option_context('display.max_colwidth', None,
'display.max_columns', None,
'display.max_rows', None):
display(df)
Excel 저장하기
write an object to an Excel sheet using pd.DataFrame.to_excel()
df.to_excel(
xlxs_dir, # directory and file name to write
sheet_name="Sheet1",
na_rep="NaN",
float_format="%.2f",
header=True,
# columns=["group", "value_1", "value_2"], # if header is False
index=True,
index_label="id",
startrow=1,
startcol=1,
# engine="xlsxwriter",
freeze_panes=(2, 0),
)
Troubelshooting
DtypeWarning: Columns (5) have mixed types
/home/your/Project/steel-reports/steelreports/apps/csv_to_sqlite/app.py:56: DtypeWarning: Columns (5) have mixed types. Specify dtype option on import or set low_memory=False.
df = pd.read_csv(filepath)
특정 Column에 데이터 타입이 혼합된 경우 (위 경고의 경우 5번째) 발생되는 경고이다. #데이터 타입 지정 방법 항목 참조.
A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method
대충 다음과 같은 에러 출력됨:
/home/your/Project/vrs/vrs/assets/_append_recommendation_rate.py:29: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.
For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.
df[COL_RECOMMENDATION_RATE].fillna(0.0, inplace=True)
다음과 같이 수정:
numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject
import pandas
로 판다스를 임포트하자마자 다음과 같은 에러 출력:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/your/Project/your-api/.venv/lib/python3.11/site-packages/pandas/__init__.py", line 22, in <module>
from pandas.compat import is_numpy_dev as _is_numpy_dev # pyright: ignore # noqa:F401
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/your/Project/your-api/.venv/lib/python3.11/site-packages/pandas/compat/__init__.py", line 18, in <module>
from pandas.compat.numpy import (
File "/home/your/Project/your-api/.venv/lib/python3.11/site-packages/pandas/compat/numpy/__init__.py", line 4, in <module>
from pandas.util.version import Version
File "/home/your/Project/your-api/.venv/lib/python3.11/site-packages/pandas/util/__init__.py", line 2, in <module>
from pandas.util._decorators import ( # noqa:F401
File "/home/your/Project/your-api/.venv/lib/python3.11/site-packages/pandas/util/_decorators.py", line 14, in <module>
from pandas._libs.properties import cache_readonly
File "/home/your/Project/your-api/.venv/lib/python3.11/site-packages/pandas/_libs/__init__.py", line 13, in <module>
from pandas._libs.interval import Interval
File "pandas/_libs/interval.pyx", line 1, in init pandas._libs.interval
ValueError: numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject
numpy 버전이 2.x 라면 1.x 버전으로 낮춰보자.
FutureWarning: ... Don't supply a list with a single grouper to avoid this warning.
/home/your/Project/steel-reports/steelreports/apps/report/app.py:344: FutureWarning: In a future version of pandas, a length 1 tuple will be returned when iterating over a groupby with a grouper equal to a list of length 1. Don't supply a list with a single grouper to avoid this warning.
for key, g0 in groups0:
이 경고는 Pandas의 향후 버전에서 groupby 메서드의 동작이 변경될 것임을 알려줍니다.
문제는 groupby를 호출할 때 그룹화 기준으로 리스트를 사용하는 경우 발생합니다. 특히 그룹화 기준이 리스트로 되어 있지만 리스트 안에 단일 요소만 있을 때 이런 경고가 나타납니다.
수정 후:
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
df[k.header.group] = is_new_group.cumsum() + 1
/home/your/Project/steel-reports/steelreports/apps/report/app.py:247: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
SettingWithCopyWarning은 Pandas에서 DataFrame의 슬라이스에서 값을 수정하려고 할 때 발생하는 경고입니다. 이 경고는 데이터가 복사된 버전인지 원본인지 확실하지 않다는 것을 나타냅니다. 이로 인해 의도하지 않은 동작이 발생할 수 있으므로 이를 수정하는 것이 좋습니다.
원본 코드:
@staticmethod
def push_grapple_group(df: DataFrame) -> DataFrame:
is_new_group = df[k.header.grapple] <= df[k.header.grapple].shift(1)
assert isinstance(is_new_group, Series)
df[k.header.group] = is_new_group.cumsum() + 1
return df
.loc
를 사용하면 된다.
@staticmethod
def push_grapple_group(df: DataFrame) -> DataFrame:
is_new_group = df[k.header.grapple] <= df[k.header.grapple].shift(1)
assert isinstance(is_new_group, Series)
df.loc[:, k.header.group] = is_new_group.cumsum() + 1
return df
근데 난 위 방법을 썼는데 경고가 출력되더라. 그래서 .copy()
를 사용하여 객체를 복사한 후 반환했다:
@staticmethod
def push_grapple_group(df: DataFrame) -> DataFrame:
df = df.copy()
is_new_group = df[k.header.grapple] <= df[k.header.grapple].shift(1)
assert isinstance(is_new_group, Series)
df[k.header.group] = is_new_group.cumsum() + 1
return df