ERROR:root:Error analyzing city Budva: unsupported operand type(s) for *: 'NoneType' and 'float'
ERROR:root:Error analyzing city : can't multiply sequence by non-int of type 'float'


bu hataları düzelt ve hesaplama algoritmanda bir düzenleme yap İstanbul gibi bir şehir

3 score alıp 683 gibi bir sıralamada bulunuyor bu da pek mantıklı değil. yani sıralama hesaplaması pek tutarlı değil


import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import json
from colorama import Fore, Style, init
import logging
from datetime import datetime
from statistics import mean, median

class CityAnalyzer:
    def __init__(self, cities_data):
        self.scaler = MinMaxScaler(feature_range=(0, 5))
        
        # Veri setinden ortalama değerleri hesapla
        self.calculate_defaults(cities_data)
        
        # Önemli faktörler için ağırlıklar (dengeli dağıtım)
        self.weights = {
            'safety_weight': 0.25,  # Güvenlik en önemli faktör
            'cost_weight': 0.20,    # Maliyet ikinci önemli faktör
            'quality_weight': 0.20,  # Yaşam kalitesi
            'infrastructure_weight': 0.15,  # Altyapı
            'social_weight': 0.10,   # Sosyal faktörler
            'economy_weight': 0.10    # Ekonomi
        }

    def calculate_defaults(self, cities_data):
        """Veri setinden varsayılan değerleri hesapla"""
        safety_scores = []
        cost_of_living = []
        quality_scores = []
        internet_speeds = []
        healthcare_scores = []
        air_quality_scores = []
        
        for city in cities_data:
            # Güvenlik skorları
            if city.get('scores', {}).get('safety'):
                safety_scores.append(city['scores']['safety'])
            
            # Yaşam maliyeti
            if city.get('costs', {}).get('nomad_cost'):
                cost_of_living.append(city['costs']['nomad_cost'])
            
            # Yaşam kalitesi
            if city.get('scores', {}).get('quality_of_life'):
                quality_scores.append(city['scores']['quality_of_life'])
            
            # Internet hızı
            if city.get('guides', {}).get('internet_speed_avg'):
                internet_speeds.append(city['guides']['internet_speed_avg'])
            
            # Sağlık hizmetleri
            if city.get('scores', {}).get('healthcare'):
                healthcare_scores.append(city['scores']['healthcare'])
            
            # Hava kalitesi
            if city.get('guides', {}).get('air_quality_avg'):
                air_quality_scores.append(city['guides']['air_quality_avg'])

        # Varsayılan değerleri medyan değerler olarak ayarla
        self.default_values = {
            'safety': median(safety_scores) if safety_scores else 3.5,
            'cost_of_living': median(cost_of_living) if cost_of_living else 2000,
            'quality_of_life': median(quality_scores) if quality_scores else 3.0,
            'internet_speed': median(internet_speeds) if internet_speeds else 20,
            'healthcare': median(healthcare_scores) if healthcare_scores else 3.0,
            'air_quality': median(air_quality_scores) if air_quality_scores else 50
        }

    def normalize_score(self, value, min_val, max_val, inverse=False):
        """Değerleri 0-5 aralığına normalize et"""
        if value is None:
            return None
        
        normalized = ((value - min_val) / (max_val - min_val)) * 5
        if inverse:
            normalized = 5 - normalized
        return min(max(normalized, 0), 5)

    def calculate_safety_score(self, city_data):
        safety = city_data.get('scores', {}).get('safety', self.default_values['safety'])
        traffic_safety = city_data.get('scores', {}).get('traffic_safety', self.default_values['safety'])
        female_friendly = city_data.get('scores', {}).get('female_friendly', self.default_values['safety'])
        
        weights = [0.4, 0.3, 0.3]  # Güvenlik faktörlerinin ağırlıkları
        scores = [
            safety if safety is not None else self.default_values['safety'],
            traffic_safety if traffic_safety is not None else self.default_values['safety'],
            female_friendly if female_friendly is not None else self.default_values['safety']
        ]
        
        return sum(score * weight for score, weight in zip(scores, weights))

    def calculate_cost_score(self, city_data):
        nomad_cost = city_data.get('costs', {}).get('nomad_cost')
        expat_cost = city_data.get('costs', {}).get('expat_cost')
        
        if nomad_cost is None and expat_cost is None:
            return 2.5  # Orta değer
        
        costs = []
        if nomad_cost is not None:
            costs.append(self.normalize_score(nomad_cost, 500, 5000, inverse=True))
        if expat_cost is not None:
            costs.append(self.normalize_score(expat_cost, 300, 4000, inverse=True))
        
        return np.mean(costs)

    def calculate_quality_score(self, city_data):
        quality = city_data.get('scores', {}).get('quality_of_life')
        healthcare = city_data.get('scores', {}).get('healthcare')
        air_quality = city_data.get('guides', {}).get('air_quality_avg')
        
        weights = [0.4, 0.4, 0.2]  # Yaşam kalitesi faktörlerinin ağırlıkları
        scores = [
            quality if quality is not None else self.default_values['quality_of_life'],
            healthcare if healthcare is not None else self.default_values['healthcare'],
            5 - (air_quality / 20) if air_quality is not None else (5 - self.default_values['air_quality'] / 20)
        ]
        
        return sum(score * weight for score, weight in zip(scores, weights))

    def calculate_infrastructure_score(self, city_data):
        wifi = city_data.get('scores', {}).get('wifi')
        walking = city_data.get('scores', {}).get('walking_available')
        internet_speed = city_data.get('guides', {}).get('internet_speed_avg')
        
        weights = [0.4, 0.3, 0.3]
        scores = [
            wifi if wifi is not None else 2.5,
            walking if walking is not None else 2.5,
            self.normalize_score(internet_speed, 5, 100) if internet_speed is not None else 2.5
        ]
        
        return sum(score * weight for score, weight in zip(scores, weights))

    def calculate_social_score(self, city_data):
        lack_of_racism = city_data.get('scores', {}).get('lack_of_racism', 2.5)
        lgbtq_friendly = city_data.get('scores', {}).get('lgbtq_friendly', 2.5)
        english_speaking = city_data.get('scores', {}).get('english_speaking', 2.5)
        
        weights = [0.4, 0.3, 0.3]
        scores = [lack_of_racism, lgbtq_friendly, english_speaking]
        
        return sum(score * weight for score, weight in zip(scores, weights))

    def calculate_economy_score(self, city_data):
        startup_score = city_data.get('scores', {}).get('startup_score', 2.5)
        gdp_per_capita = city_data.get('guides', {}).get('gdp_per_capita')
        
        gdp_score = self.normalize_score(gdp_per_capita, 5000, 100000) if gdp_per_capita is not None else 2.5
        
        return np.mean([startup_score, gdp_score])

    def calculate_total_score(self, city_data):
        scores = {
            'safety': self.calculate_safety_score(city_data),
            'cost': self.calculate_cost_score(city_data),
            'quality': self.calculate_quality_score(city_data),
            'infrastructure': self.calculate_infrastructure_score(city_data),
            'social': self.calculate_social_score(city_data),
            'economy': self.calculate_economy_score(city_data)
        }
        
        weighted_score = sum(
            scores[score_type.replace('_weight', '')] * weight
            for score_type, weight in self.weights.items()
        )
        
        return round(weighted_score, 2)

    def analyze_cities(self, cities_data):
        analyzed_cities = []
        
        for city in cities_data:
            try:
                city_name = city['general']['name']
                total_score = self.calculate_total_score(city)
                
                analyzed_city = {
                    **city,
                    'city_total_score': total_score,
                    'analysis_details': {
                        'safety_score': self.calculate_safety_score(city),
                        'cost_score': self.calculate_cost_score(city),
                        'quality_score': self.calculate_quality_score(city),
                        'infrastructure_score': self.calculate_infrastructure_score(city),
                        'social_score': self.calculate_social_score(city),
                        'economy_score': self.calculate_economy_score(city)
                    }
                }
                analyzed_cities.append(analyzed_city)
                logging.info(f"Successfully analyzed {city_name} with score {total_score}")
                
            except Exception as e:
                logging.error(f"Error analyzing city {city.get('general', {}).get('name', 'Unknown')}: {str(e)}")
        
        # Şehirleri toplam puana göre sıralama
        analyzed_cities.sort(key=lambda x: x['city_total_score'], reverse=True)
        
        # Sıralama ekle
        for rank, city in enumerate(analyzed_cities, 1):
            city['city_rank'] = rank
        
        return analyzed_cities

def main():
    init(autoreset=True)
    
    try:
        # Veriyi oku
        with open('data/23.10.2024/demo_cities_updated.json', 'r', encoding='utf-8') as file:
            cities_data = json.load(file)
        
        # Analiz yap
        analyzer = CityAnalyzer(cities_data)  # Veri setini constructor'a geçir
        analyzed_cities = analyzer.analyze_cities(cities_data)
        
        # Sonuçları kaydet
        with open('data/appendCityClaude.json', 'w', encoding='utf-8') as file:
            json.dump(analyzed_cities, file, indent=2, ensure_ascii=False)
        
        print(f"{Fore.GREEN}Analysis completed successfully!")
        print(f"{Fore.CYAN}Top 5 Cities:")
        for city in analyzed_cities[:5]:
            print(f"{Fore.YELLOW}Rank {city['city_rank']}: {city['general']['name']} - Score: {city['city_total_score']}")
            
    except Exception as e:
        print(f"{Fore.RED}An error occurred: {str(e)}")
        logging.error(f"Main execution error: {str(e)}")

if __name__ == "__main__":
    main()

örnek veri seti

[
  {
    "url": "https://nomads.com/minot",
    "short_slug": "minot",
    "general": {
      "name": "Minot, ND",
      "long_slug": "minot-nd-united-states",
      "continent": "North America",
      "country": "United States",
      "latitude": 48.2325,
      "longitude": -101.2963,
      "similar_cities": [
        {
          "name": "Las Vegas, NV",
          "country": "United States",
          "country_slug": "united-states",
          "short_slug": "las-vegas",
          "distance_time": 120,
          "vehicle_type": "plane"
        },
      ],
      "near_cities": [
        {
          "name": "Billings, MT",
          "country": "United States",
          "country_slug": "united-states",
          "short_slug": "billings",
          "distance_time": 50,
          "vehicle_type": "plane"
        },
      ],
      "pros": [
        "Pretty safe",
        "Fast internet",
        "Perfect humidity now",
        "Good air quality on average",
        "Spacious and not crowded",
        "Very easy to do business",
        "High quality of education",
        "Great hospitals",
        "Roads are very safe",
        "Great freedom of speech",
        "Democratic",
        "Everyone speaks English",
        "Very safe for women",
        "Family friendly",
        "Very friendly to LGBTQ+",
        "Not many people smoke tobacco",
        "(Medical) marijuana MAY be legal, unenforced or decriminalized (always double check this)"
      ],
      "cons": [
        "Very expensive",
        "Not much to do",
        "Gets very cold in the winter",
        "Difficult to make friends",
        "High alcohol consumption"
      ]
    },
    "scores": {
      "nightlife": 3.0,
      "working_places": null,
      "family_friendly": 3.5659197347,
      "safety": 4,
      "quality_of_life": 3.4022399375,
      "education": 4.3888888889,
      "wifi": 4.0,
      "fun": 3.0,
      "walking_available": 5.0,
      "healthcare": 4.3790746144,
      "lack_of_racism": 4.5,
      "english_speaking": 5.0,
      "traffic_safety": 3.0,
      "foreigners_friendly": null,
      "female_friendly": 4.0,
      "lgbtq_friendly": 5.0,
      "startup_score": 2.9846505973
    },
    "guides": {
      "average_trip_length": null,
      "internet_speed_avg": 35.0,
      "air_quality_avg": 18,
      "power": {
        "plug_types": ["American-type A-plug"],
        "voltage": "115V",
        "frequency": "60Hz"
      },
      "suggested_atm_take_out": null,
      "tipping": { "value": 1, "description": "15% tipping" },
      "cashless": { "value": 1, "description": "Cards OK almost everywhere" },
      "tap_water": 1,
      "return_rate": null,
      "visitors_per_year": null,
      "tourists_now": null,
      "population": 46000,
      "gdp_per_capita": 57808,
      "density": null,
      "religious_government": 0,
      "male_percent": null,
      "female_percent": null,
      "apartment_listings": {
        "name": "Craigslist",
        "url": "http://craigslist.org",
        "logo": "https://logo.clearbit.com/craigslist.org"
      },
      "best_short_haul_air_carrier": null,
      "best_intl_air_carrier": {
        "name": "Delta",
        "url": "http://www.delta.com/",
        "logo": "https://logo.clearbit.com/www.delta.com/"
      },
      "best_taxi_app": {
        "name": "Uber",
        "url": "http://uber.com",
        "logo": null
      },
      "best_hospital": {
        "name": "Trinity Health Minot",
        "url": "http://www.trinityhealth.org/",
        "logo": "https://logo.clearbit.com/www.trinityhealth.org/"
      },
      "online_electronics_shop": {
        "name": "Amazon",
        "url": "https://amazon.com",
        "logo": "https://logo.clearbit.com/amazon.com"
      }
    },
    "costs": {
      "nomad_cost": 3439.35,
      "expat_cost": 2109.53,
      "family_cost": 5396.35,
      "local_cost": 1541.81,
      "hotel_price_median": 1964.2,
      "airbnb_median": 1244.76,
      "apartment_1bedroom": 1086.0,
      "coworking_hot_desk": 235.0,
      "water": null,
      "banana": null,
      "meat": null,
      "chicken_breast": null,
      "potato": null,
      "dinner": 16.0,
      "coca_cola": 2.0,
      "beer_in_cafe": 5.0,
      "international_school": 4000.0,
      "mobile_data": 4.0,
      "taxi_1km": 4.0
    }
  },
  {
    "url": "https://nomads.com/istanbul",
    "short_slug": "istanbul",
    "general": {
      "name": "Istanbul",
      "long_slug": "istanbul-turkey",
      "continent": "Europe",
      "country": "Turkey",
      "latitude": 41.00527,
      "longitude": 28.97696,
      "similar_cities": [
        {
          "name": "Athens",
          "country": "Greece",
          "country_slug": "greece",
          "short_slug": "athens",
          "distance_time": 45,
          "vehicle_type": "plane"
        },
      ],
      "pros": [
        "Rich historical and cultural experience",
        "Beautiful architecture and sights",
        "Affordable food and living costs",
        "Variety of cafes with reliable WiFi",
        "Decent public transport options",
        "Generally safe for night walks",
        "Vibrant nightlife",
        "Helpful locals in certain areas",
        "Affordable to live",
        "Pretty safe",
        "Fast internet",
        "Perfect humidity now",
        "Many Nomads.com members here all year round",
        "Easy to make friends",
        "Easy to do business",
        "High quality of education",
        "Great hospitals",
        "Roads are pretty safe",
        "LGBTQ+ friendly",
        "Not a lot of alcohol abuse"
      ],
      "cons": [
        "Rude and unwelcoming locals",
        "Language barrier (limited English speakers)",
        "Frequent scams, especially by taxi drivers",
        "High Airbnb prices and variable quality",
        "Crowded and chaotic city environment",
        "Overwhelming tourist traps",
        "Unsafe feeling in specific areas",
        "Freedom of speech is weak",
        "Not very democratic",
        "Not much to do",
        "Cold now",
        "Gets cold in the winter",
        "Nomads.com members didn't like going here",
        "Feels crowded",
        "People don't speak English well",
        "Not safe for women",
        "Not family friendly",
        "Many people smoke tobacco",
        "Marijuana is illegal"
      ],
      "country_code": "TR"
    },
    "scores": {
      "nightlife": 5.0,
      "working_places": 5.0,
      "family_friendly": 2.8357638794,
      "safety": 4,
      "quality_of_life": 3.2181031257,
      "education": 3.0666666667,
      "wifi": 3.0,
      "fun": 3.0,
      "walking_available": 5.0,
      "healthcare": 4.836932055,
      "lack_of_racism": 2.0,
      "english_speaking": 2.2749077491,
      "traffic_safety": 3.0,
      "foreigners_friendly": 3.0,
      "female_friendly": 2.0,
      "lgbtq_friendly": 3.0,
      "startup_score": 2.4534025413
    },
    "guides": {
      "average_trip_length": 10,
      "internet_speed_avg": 28.0,
      "air_quality_avg": 111,
      "power": {
        "plug_types": ["European-type C-plug"],
        "voltage": "230V",
        "frequency": "50Hz"
      },
      "suggested_atm_take_out": 292,
      "tipping": {
        "value": 1,
        "description": "7.50% tipping"
      },
      "cashless": null,
      "tap_water": 0,
      "return_rate": 17,
      "visitors_per_year": 8642300,
      "tourists_now": 165629,
      "population": 15000000,
      "gdp_per_capita": 10863,
      "density": 100,
      "religious_government": 1,
      "male_percent": null,
      "female_percent": null,
      "apartment_listings": {
        "name": "Sahibinden",
        "url": "http://sahibinden.com",
        "logo": "https://logo.clearbit.com/sahibinden.com"
      },
      "best_short_haul_air_carrier": {
        "name": "AnadoluJet",
        "url": "http://www.anadolujet.com",
        "logo": "https://logo.clearbit.com/www.anadolujet.com"
      },
      "best_intl_air_carrier": {
        "name": "Turkish",
        "url": "http://www.turkishairlines.com",
        "logo": "https://logo.clearbit.com/www.turkishairlines.com"
      },
      "best_taxi_app": {
        "name": "Uber",
        "url": "http://uber.com",
        "logo": null
      },
      "best_hospital": null,
      "online_electronics_shop": {
        "name": "Hepsiburada",
        "url": "https://hepsiburada.com",
        "logo": "https://logo.clearbit.com/hepsiburada.com"
      }
    },
    "costs": {
      "nomad_cost": 1665.9,
      "expat_cost": 947.28,
      "family_cost": 1717.26,
      "local_cost": 490.65,
      "hotel_price_median": 1544.81,
      "airbnb_median": 1598.11,
      "apartment_1bedroom": 355.11,
      "coworking_hot_desk": 92.5,
      "water": null,
      "banana": null,
      "meat": null,
      "chicken_breast": null,
      "potato": null,
      "dinner": 4.09,
      "coca_cola": 0.61,
      "beer_in_cafe": 2.04,
      "international_school": 4971.57,
      "mobile_data": 4.67,
      "taxi_1km": 0.88
    }
  }
]