|
| 1 | +import pandas as pd |
| 2 | + |
| 3 | +# The extended_landbosse_details dataframe includes all the details along side |
| 4 | +# all the project list inputs |
| 5 | +print("Reading extended details...") |
| 6 | +df = pd.read_csv("extended_landbosse_details.csv") |
| 7 | + |
| 8 | +# Extract the crane choice data |
| 9 | +print("Selecting erection data...") |
| 10 | +erection_df = df.query("`Module` == 'ErectionCost'")[[ |
| 11 | + "Project ID with serial", |
| 12 | + "Variable name", |
| 13 | + "Numeric value", |
| 14 | + "Non-numeric value", |
| 15 | + "Number of turbines", |
| 16 | + "Turbine rating MW", |
| 17 | + "Hub height m", |
| 18 | + "Labor cost multiplier", |
| 19 | + "Crane breakdown fraction", |
| 20 | + "Breakpoint between base and topping (percent)", |
| 21 | + "Total project construction time (months)" |
| 22 | +]] |
| 23 | + |
| 24 | +aligned_erection_rows = [] |
| 25 | + |
| 26 | +print("Selecting unique projects...") |
| 27 | +unique_project_id_with_serial = erection_df['Project ID with serial'].unique() |
| 28 | + |
| 29 | +print("Rearranging crane detail data from rows into columns...") |
| 30 | +for project_id_with_serial in unique_project_id_with_serial: |
| 31 | + print(f"\t{project_id_with_serial}") |
| 32 | + |
| 33 | + # Crane data output |
| 34 | + crane_data_df = erection_df.query( |
| 35 | + "`Project ID with serial` == @project_id_with_serial and `Variable name` == 'crane_data_output: crane_boom_operation_concat - variable - value'" |
| 36 | + ) |
| 37 | + top_wind_multiplier_row = crane_data_df[crane_data_df["Non-numeric value"].str.contains("Top - Wind multiplier")] |
| 38 | + base_wind_multiplier_row = crane_data_df[crane_data_df["Non-numeric value"].str.contains("Base - Wind multiplier")] |
| 39 | + offload_wind_multiplier_row = crane_data_df[crane_data_df["Non-numeric value"].str.contains("Offload - Wind multiplier")] |
| 40 | + top_wind_multiplier = top_wind_multiplier_row["Numeric value"].values[0] |
| 41 | + offload_wind_multiplier = offload_wind_multiplier_row["Numeric value"].values[0] |
| 42 | + if len(base_wind_multiplier_row) > 0: |
| 43 | + base_wind_multiplier = base_wind_multiplier_row["Numeric value"].values[0] |
| 44 | + else: |
| 45 | + base_wind_multiplier = None |
| 46 | + |
| 47 | + # Re-using crane_data_df from above, operation time for all turbines |
| 48 | + top_operation_time_hours_row = crane_data_df[ |
| 49 | + crane_data_df["Non-numeric value"].str.contains("Top - Operation time all turbines hrs")] |
| 50 | + offload_operation_time_hours_row = crane_data_df[ |
| 51 | + crane_data_df["Non-numeric value"].str.contains("Offload - Operation time all turbines hrs")] |
| 52 | + base_operation_time_hours_row = crane_data_df[ |
| 53 | + crane_data_df["Non-numeric value"].str.contains("Base - Operation time all turbines hrs")] |
| 54 | + top_operation_time_hours = top_operation_time_hours_row["Numeric value"].values[0] |
| 55 | + offload_operation_time_hours = offload_operation_time_hours_row["Numeric value"].values[0] |
| 56 | + if len(base_operation_time_hours_row) > 0: |
| 57 | + base_operation_time_hours = base_operation_time_hours_row["Numeric value"].values[0] |
| 58 | + else: |
| 59 | + base_operation_time_hours = None |
| 60 | + |
| 61 | + # Crane cost details |
| 62 | + crane_cost_df = erection_df.query( |
| 63 | + "`Project ID with serial` == @project_id_with_serial and `Variable name` == 'crane_cost_details: Operation ID - Type of cost - Cost'" |
| 64 | + ) |
| 65 | + top_total_cost_row = crane_cost_df[crane_cost_df["Non-numeric value"].str.contains("Top - Total cost USD")] |
| 66 | + base_total_cost_row = crane_cost_df[crane_cost_df["Non-numeric value"].str.contains("Base - Total cost USD")] |
| 67 | + offload_total_cost_row = crane_cost_df[crane_cost_df["Non-numeric value"].str.contains("Offload - Total cost USD")] |
| 68 | + top_total_cost = top_total_cost_row["Numeric value"].values[0] |
| 69 | + offload_total_cost = offload_total_cost_row["Numeric value"].values[0] |
| 70 | + if len(base_total_cost_row) > 0: |
| 71 | + base_total_cost = base_total_cost_row["Numeric value"].values[0] |
| 72 | + else: |
| 73 | + base_total_cost = None |
| 74 | + |
| 75 | + # Crane choice |
| 76 | + crane_choice_rows_df = erection_df.query( |
| 77 | + "`Project ID with serial` == @project_id_with_serial and `Variable name` == 'crane_choice: Crew name - Boom system - Operation'" |
| 78 | + ) |
| 79 | + top_row = crane_choice_rows_df[crane_choice_rows_df["Non-numeric value"].str.contains("Top")] |
| 80 | + base_row = crane_choice_rows_df[crane_choice_rows_df["Non-numeric value"].str.contains("Base")] |
| 81 | + offload_row = crane_choice_rows_df[crane_choice_rows_df["Non-numeric value"].str.contains("Offload")] |
| 82 | + offload = " ".join(offload_row["Non-numeric value"].values[0].split(" - ")[:-1]) |
| 83 | + top = " ".join(top_row["Non-numeric value"].values[0].split(" - ")[:-1]) |
| 84 | + if len(base_row) > 0: |
| 85 | + base = " ".join(base_row["Non-numeric value"].values[0].split(" - ")[:-1]) |
| 86 | + else: |
| 87 | + base = None |
| 88 | + |
| 89 | + aligned_erection_row = { |
| 90 | + "Project ID with serial": project_id_with_serial, |
| 91 | + "Number of turbines": top_row["Number of turbines"].values[0], |
| 92 | + "Breakpoint between base and topping (percent)": \ |
| 93 | + top_row["Breakpoint between base and topping (percent)"].values[0], |
| 94 | + "Turbine rating MW": top_row["Turbine rating MW"].values[0], |
| 95 | + "Crane breakdown fraction": top_row["Crane breakdown fraction"].values[0], |
| 96 | + "Labor cost multiplier": top_row["Labor cost multiplier"].values[0], |
| 97 | + "Hub height m": top_row["Hub height m"].values[0], |
| 98 | + "Base crane choice": base, |
| 99 | + "Offload crane choice": offload, |
| 100 | + "Top crane choice": top, |
| 101 | + "Base total cost": |
| 102 | + round(float(base_total_cost), 0) if base_total_cost is not None else None, |
| 103 | + "Offload total cost": round(float(offload_total_cost), 0), |
| 104 | + "Top total cost": round(float(top_total_cost), 0), |
| 105 | + "Base wind multiplier": |
| 106 | + round(float(base_wind_multiplier), 2) if base_wind_multiplier is not None else None, |
| 107 | + "Offload wind multiplier": round(float(offload_wind_multiplier), 2), |
| 108 | + "Top wind multiplier": round(float(top_wind_multiplier), 2), |
| 109 | + "Base operation time all turbines (hours)": |
| 110 | + round(float(base_operation_time_hours), 0) if base_operation_time_hours is not None else None, |
| 111 | + "Offload operation time all turbines (hours)": round(float(offload_operation_time_hours), 0), |
| 112 | + "Top operation time all turbines (hours)": round(float(top_operation_time_hours), 0) |
| 113 | + } |
| 114 | + |
| 115 | + aligned_erection_rows.append(aligned_erection_row) |
| 116 | + |
| 117 | +print("Writing crane choices...") |
| 118 | +aligned_crane_choice_df = pd.DataFrame(aligned_erection_rows) |
| 119 | +aligned_crane_choice_df.to_csv("crane_details.csv", index=False) |
0 commit comments