我有一个巨大的pandas数据帧,形状为(700,000, 5,000),包含各种类型的列(主要是int8,一些float64和几个datetime64[ns])。对于数据框中的每一行,如果另一列也等于零,我想将某些列的值设置为零。
如果我迭代数据框并使用iloc设置值,则速度非常慢。我尝试过iterrows和itertuples,例如:
1.使用iterrows方法
有没有更好的方法让我首先进行更新?
如果没有,那么我应该如何保持我的数据类型不变(日期时间列不在要更改的列列表中,如果相关的话)?
或者,也许有一种更好的方法可以使用更新后的numpy数组来更新原始数据框,其中我只更新了更改的列(所有这些列都是int8)?
更新
根据评论的要求,这里是一个最小的示例,说明int8数据类型在降入numpy后变为对象数据类型。 明确地说,这仅适用于上述第4种方法(这是我目前唯一的非慢速方法 - 如果我可以解决此数据类型问题)。
如果我迭代数据框并使用iloc设置值,则速度非常慢。我尝试过iterrows和itertuples,例如:
1.使用iterrows方法
ix_1 = 3
ix_to_change = [20, 24, 51] # Actually it is almost 5000 columns to change
for i, row in df.iterrows():
if not row[ix_1]:
df.iloc[i, ix_to_change] = 0
2. itertuples:
ix_1 = 3
ix_to_change = [20, 24, 51] # Actually it is almost 5000 columns to change
for row in df.itertuples():
if not row[ix_1 + 1]:
df.iloc[row[0], ix_to_change] = 0
我也尝试过使用pandas索引,但它仍然很慢(虽然比iterrows或itertuples好)。
3. pandas loc & iloc
df.loc[df.iloc[:, ix_1]==0, df.columns[ix_to_change]] = 0
我尝试过降低到底层的numpy数组,性能方面很好,但是我在dtype方面遇到了问题。
它快速地迭代底层数组,但新的数据框架具有所有“对象”dtype。如果我尝试按列设置dtype(如此示例),则会在日期时间列上失败 - 可能是因为它们包含NaT项。
4. numpy
X = df.values
for i, x in enumerate(X):
if not x[ix_1]:
X[i].put(ix_to_change, 0)
original_dtypes = df.dtypes
df = pd.DataFrame(data=X, index=df.index, columns=df.columns)
for col, col_dtype in original_dtypes.items():
df[c] = df[c].astype(col_dtype)
有没有更好的方法让我首先进行更新?
如果没有,那么我应该如何保持我的数据类型不变(日期时间列不在要更改的列列表中,如果相关的话)?
或者,也许有一种更好的方法可以使用更新后的numpy数组来更新原始数据框,其中我只更新了更改的列(所有这些列都是int8)?
更新
根据评论的要求,这里是一个最小的示例,说明int8数据类型在降入numpy后变为对象数据类型。 明确地说,这仅适用于上述第4种方法(这是我目前唯一的非慢速方法 - 如果我可以解决此数据类型问题)。
import pandas as pd
df = pd.DataFrame({'int8_col':[10,11,12], 'float64_col':[1.5, 2.5, 3.5]})
df['int8_col'] = df['int8_col'].astype('int8')
df['datetime64_col'] = pd.to_datetime(['2018-01-01', '2018-01-02', '2018-01-03'])
>>> df.dtypes
float64_col float64
int8_col int8
datetime64_col datetime64[ns]
dtype: object
X = df.values
# At this point in real life I modify the int8 column(s) only in X
new_df = pd.DataFrame(data=X, index=df.index, columns=df.columns)
>>> new_df.dtypes
float64_col object
int8_col object
datetime64_col object
dtype: object
X = df.values
。不要这样做,因为单个NumPy数组只能有一个dtype。在Pandas内部,每个系列都有一个单独的NumPy数组/ dtype。你可以使用Pandas来利用这一点。 - jpp