我想保存数据帧的一些属性并给出底层numpy数组的一部分,我想重建数据帧,好像我已经采用了一片数据帧。如果一个对象列的值可以强制转换为浮点数,我无法找出任何可行的方法。在真实数据集中,我有数百万个观察点和数百个列。
实际用例涉及pandas与scikit-learn交互的自定义代码。我知道scikit-learn的最新版本与内置的pandas兼容,但我无法使用此版本,因为RandomizedSearchCV对象无法处理大型参数网格(这将在未来的版本中修复)。
data = [[2, 4, "Focus"],
[3, 4, "Fiesta",],
[1, 4, "300"],
[7, 3, "Pinto"]]
# This dataframe is exactly as intended
df = pd.DataFrame(data=data)
# Slice a subset of the underlying numpy array
raw_slice = df.values[1:,:]
# Try using the dtype option to force dtypes
df_dtype = pd.DataFrame(data=raw_slice, dtype=df.dtypes)
print "\n Dtype arg doesn't use passed dtypes \n", df_dtype.dtypes
# Try converting objects to numeric after reading into dataframe
df_convert = pd.DataFrame(data=raw_slice).convert_objects(convert_numeric=True)
print "\n Convert objects drops object values that are not numeric \n", df_convert
[Out]
Converted data does not use passed dtypes
0 object
1 object
2 object
dtype: object
Converted data drops object values that are not numeric
0 1 2
0 3 4 NaN
1 1 4 300
2 7 3 NaN
编辑: 谢谢@unutbu的答案,它正好回答了我的问题。在0.16.0之前的scikit-learn版本中,gridsearch对象从pandas数据帧中剥离了底层的numpy数组。这意味着单个对象列使整个数组成为对象,并且pandas方法无法包含在自定义转换器中。
解决方案,使用@ unutbu的答案是使管道的第一步成为自定义的“DataFrameTransformer”对象。
class DataFrameTransformer(BaseEstimator, TransformerMixin):
def __init__(self, X):
self.columns = list(X.columns)
self.dtypes = X.dtypes
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
X = pd.DataFrame(X, columns=self.columns)
for col, dtype in zip(X, self.dtypes):
X[col] = X[col].astype(dtype)
return X
在管道中,只需在构造函数中包含原始df:
pipeline = Pipeline([("df_converter", DataFrameTransformer(X)),
...,
("rf", RandomForestClassifier())])
答案 0 :(得分:1)
如果您尝试将一片DataFrame保存到磁盘,那么功能强大且可以
方便的方法是使用pd.HDFStore
。请注意,这需要
要安装的PyTables。
# To save the slice `df.iloc[1:, :]` to disk:
filename = '/tmp/test.h5'
with pd.HDFStore(filename) as store:
store['mydata'] = df.iloc[1:, :]
# To load the DataFrame from disk:
with pd.get_store(filename) as store:
newdf2 = store['mydata']
print(newdf2.dtypes)
print(newdf2)
产量
0 int64
1 int64
2 object
dtype: object
0 1 2
0 3 4 Fiesta
1 1 4 300
2 7 3 Pinto
从NumPy数组(对象dtype!)重建子DataFrame
和df.dtypes
,您可以使用
import pandas as pd
data = [[2, 4, "Focus"],
[3, 4, "Fiesta",],
[1, 4, "300"],
[7, 3, "Pinto"]]
# This dataframe is exactly as intended
df = pd.DataFrame(data=data)
# Slice a subset of the `values` numpy object array
raw_slice = df.values[1:,:]
newdf = pd.DataFrame(data=raw_slice)
for col, dtype in zip(newdf, df.dtypes):
newdf[col] = newdf[col].astype(dtype)
print(newdf.dtypes)
print(newdf)
产生与上述相同的结果。但是,如果你没有保存
raw_slice
到磁盘,然后你可以简单地保持一个
引用df.iloc[1:, :]
而不是将数据转换为NumPy数组
object dtype - 一种效率相对较低的数据结构(就内存和内存而言)
性能)。