iterrows yields an index and a Series built from the row. A Series has one dtype, so a row mixing an int column and a float column comes back with the int upcast to float, and a row mixing numbers with strings comes back entirely as object. Code that does if row["count"] == 3 after arithmetic can therefore compare floats where integers were stored, and type(row["id"]) reports numpy.float64 instead of numpy.int64.
This is documented behaviour and not fixable by an argument. itertuples() preserves per-column dtypes because it yields a namedtuple, and it is substantially faster because no Series is constructed per row.
Better still, avoid row iteration. Most loops over iterrows are a vectorised expression written the long way, and the vectorised form runs in C over the whole column. When you truly need per-row Python, itertuples(index=False, name=None) yielding plain tuples is the fastest of the iteration options. Never mutate the frame while iterating; the changes are made to the yielded copy.