You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R中转换DataFrame格式:按ID生成年度居住记录

Solution to Transform Residence DataFrame to Annual Records

Got it, let's work through this problem to transform your DataFrame exactly as you need. Here's a step-by-step solution using pandas, which handles generating annual records (2013-2018) for each ID and populating the address based on the longest residence period in each year.


Step 1: Prepare the Input DataFrame

First, let's set up your sample data (with the END_DATE NA already replaced by 2018-12-31) and convert date columns to datetime type for easy calculations:

import pandas as pd
from datetime import datetime

# Sample input data (matches your current format)
data = {
    'ID': [1, 1, 2],
    'ZIPCODE': ['1234AB', '5678CD', '9012EF'],
    'CITY': ['NEWYORK', 'LA', 'MIAMI'],
    'ENTRY_DATE': ['2-1-2014', '13-3-2017', '10-11-2011'],
    'END_DATE': ['13-5-2017', '21-12-2018', '6-9-2017']
}

df = pd.DataFrame(data)

# Convert date columns to datetime objects (critical for date calculations)
df['ENTRY_DATE'] = pd.to_datetime(df['ENTRY_DATE'], format='%d-%m-%Y')
df['END_DATE'] = pd.to_datetime(df['END_DATE'], format='%d-%m-%Y')

Step 2: Generate All ID-Year Combinations

We need to create a base DataFrame that includes every ID paired with each year from 2013 to 2018, so we don't miss any required annual records:

# Get unique IDs and target years
unique_ids = df['ID'].unique()
target_years = range(2013, 2019)

# Create a DataFrame with all ID-Year pairs
id_year_base = pd.MultiIndex.from_product(
    [unique_ids, target_years], 
    names=['ID', 'YEAR']
).reset_index()

Step 3: Calculate Yearly Residence Duration

For each residence record, calculate how many days the person lived at that address in each target year. This helps us determine which address was the primary one for the year:

def calculate_yearly_residence_days(row, target_year):
    # Define the start/end of the target year
    year_start = datetime(target_year, 1, 1)
    year_end = datetime(target_year, 12, 31)
    
    # Find the overlap between the residence period and the target year
    overlap_start = max(row['ENTRY_DATE'], year_start)
    overlap_end = min(row['END_DATE'], year_end)
    
    # Return days of overlap (0 if no overlap)
    if overlap_start <= overlap_end:
        return (overlap_end - overlap_start).days + 1  # +1 to count both start/end days
    return 0

# Add a column for each year's residence days to the original DataFrame
for year in target_years:
    df[f'DAYS_{year}'] = df.apply(
        lambda row: calculate_yearly_residence_days(row, year), 
        axis=1
    )

Step 4: Reshape and Merge to Find Primary Address per Year

Reshape the data to long format, merge with our ID-Year base, then select the address with the longest residence time for each ID-Year pair:

# Reshape to long format (ID, ZIPCODE, CITY, YEAR, RESIDENCE_DAYS)
long_format_df = df.melt(
    id_vars=['ID', 'ZIPCODE', 'CITY'],
    value_vars=[f'DAYS_{year}' for year in target_years],
    var_name='YEAR',
    value_name='RESIDENCE_DAYS'
)

# Extract the year from the column name (e.g., "DAYS_2013" → 2013)
long_format_df['YEAR'] = long_format_df['YEAR'].str.extract('(\d+)').astype(int)

# Merge with our ID-Year base to ensure all combinations are present
merged_df = pd.merge(
    id_year_base, 
    long_format_df, 
    on=['ID', 'YEAR'], 
    how='left'
)

# Sort by residence days (descending) and keep the top row per ID-Year
final_df = merged_df.sort_values(
    ['ID', 'YEAR', 'RESIDENCE_DAYS'], 
    ascending=[True, True, False]
).groupby(['ID', 'YEAR']).first().reset_index()

# Replace entries with 0 residence days (no address that year) with NA
final_df.loc[final_df['RESIDENCE_DAYS'] == 0, ['ZIPCODE', 'CITY']] = pd.NA

# Drop the temporary RESIDENCE_DAYS column
final_df = final_df.drop('RESIDENCE_DAYS', axis=1)

Step 5: View the Final Result

When you print final_df, you'll get exactly the format you requested:

print(final_df)

Expected Output:

ID  YEAR ZIPCODE    CITY
0   1  2013    <NA>    <NA>
1   1  2014  1234AB  NEWYORK
2   1  2015  1234AB  NEWYORK
3   1  2016  1234AB  NEWYORK
4   1  2017  5678CD       LA
5   1  2018  5678CD       LA
6   2  2013  9012EF    MIAMI
7   2  2014  9012EF    MIAMI
8   2  2015  9012EF    MIAMI
9   2  2016  9012EF    MIAMI
10  2  2017  9012EF    MIAMI
11  2  2018    <NA>    <NA>

内容的提问来源于stack exchange,提问作者Matthew Turkenburg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 14:32:50