将pandas数据框转换为numpy数组,保留索引

我有兴趣了解如何将pandas数据框转换为包含索引的numpy数组,并设置dtypes。

dataframe:

label ABC ID 1 NaN 0.2 NaN 2 NaN NaN 0.5 3 NaN 0.2 0.5 4 0.1 0.2 NaN 5 0.1 0.2 0.5 6 0.1 NaN 0.5 7 0.1 NaN NaN 

转换为数组返回:

 array([[ nan, 0.2, nan], [ nan, nan, 0.5], [ nan, 0.2, 0.5], [ 0.1, 0.2, nan], [ 0.1, 0.2, 0.5], [ 0.1, nan, 0.5], [ 0.1, nan, nan]]) 

不过,我想:

 array([[ 1, nan, 0.2, nan], [ 2, nan, nan, 0.5], [ 3, nan, 0.2, 0.5], [ 4, 0.1, 0.2, nan], [ 5, 0.1, 0.2, 0.5], [ 6, 0.1, nan, 0.5], [ 7, 0.1, nan, nan]], dtype=[('ID', '<i4'), ('A', '<f8'), ('B', '<f8'), ('B', '<f8')]) 

(或类似)

有关如何完成此任何build议? (我不知道现在是否需要一维或二维数组)。我已经看到了一些涉及这个问题的文章,但没有具体涉及dataframe.index。

我正在使用to_csv写数据框磁盘(并将其读回来创build数组),但是比起我的新的pandas来说更喜欢一些更有说服力的东西。

要将pandas数据框(df)转换为numpy ndarray,请使用以下代码:

df=df.values

现在df变成了一个numpy的ndarray。

pandas有一些内置的…

 numpyMatrix = df.as_matrix() 

我只是链接DataFrame.reset_index()和DataFrame.values函数来获取dataframe的Numpy表示,包括索引:

 In [8]: df Out[8]: ABC 0 -0.982726 0.150726 0.691625 1 0.617297 -0.471879 0.505547 2 0.417123 -1.356803 -1.013499 3 -0.166363 -0.957758 1.178659 4 -0.164103 0.074516 -0.674325 5 -0.340169 -0.293698 1.231791 6 -1.062825 0.556273 1.508058 7 0.959610 0.247539 0.091333 [8 rows x 3 columns] In [9]: df.reset_index().values Out[9]: array([[ 0. , -0.98272574, 0.150726 , 0.69162512], [ 1. , 0.61729734, -0.47187926, 0.50554728], [ 2. , 0.4171228 , -1.35680324, -1.01349922], [ 3. , -0.16636303, -0.95775849, 1.17865945], [ 4. , -0.16410334, 0.0745164 , -0.67432474], [ 5. , -0.34016865, -0.29369841, 1.23179064], [ 6. , -1.06282542, 0.55627285, 1.50805754], [ 7. , 0.95961001, 0.24753911, 0.09133339]]) 

为了得到这个dtype,我们需要使用view将这个ndarray转换成一个结构化的数组:

 In [10]: df.reset_index().values.ravel().view(dtype=[('index', int), ('A', float), ('B', float), ('C', float)]) Out[10]: array([( 0, -0.98272574, 0.150726 , 0.69162512), ( 1, 0.61729734, -0.47187926, 0.50554728), ( 2, 0.4171228 , -1.35680324, -1.01349922), ( 3, -0.16636303, -0.95775849, 1.17865945), ( 4, -0.16410334, 0.0745164 , -0.67432474), ( 5, -0.34016865, -0.29369841, 1.23179064), ( 6, -1.06282542, 0.55627285, 1.50805754), ( 7, 0.95961001, 0.24753911, 0.09133339), dtype=[('index', '<i8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')]) 

你可以使用to_records方法,但是如果它们不是你想要的,就必须使用dtypes。 在我的情况下,从一个string复制你的DF,索引types是string(用pandas中的object dtype表示):

 In [102]: df Out[102]: label ABC ID 1 NaN 0.2 NaN 2 NaN NaN 0.5 3 NaN 0.2 0.5 4 0.1 0.2 NaN 5 0.1 0.2 0.5 6 0.1 NaN 0.5 7 0.1 NaN NaN In [103]: df.index.dtype Out[103]: dtype('object') In [104]: df.to_records() Out[104]: rec.array([(1, nan, 0.2, nan), (2, nan, nan, 0.5), (3, nan, 0.2, 0.5), (4, 0.1, 0.2, nan), (5, 0.1, 0.2, 0.5), (6, 0.1, nan, 0.5), (7, 0.1, nan, nan)], dtype=[('index', '|O8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')]) In [106]: df.to_records().dtype Out[106]: dtype([('index', '|O8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')]) 

转换recarray dtype不适用于我,但可以在Pandas中做到这一点:

 In [109]: df.index = df.index.astype('i8') In [111]: df.to_records().view([('ID', '<i8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')]) Out[111]: rec.array([(1, nan, 0.2, nan), (2, nan, nan, 0.5), (3, nan, 0.2, 0.5), (4, 0.1, 0.2, nan), (5, 0.1, 0.2, 0.5), (6, 0.1, nan, 0.5), (7, 0.1, nan, nan)], dtype=[('ID', '<i8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')]) 

请注意,Pandas没有在导出的logging数组(错误?)中正确设置索引的名称(对ID ),所以我们从types转换中获益,也为此进行了更正。

目前Pandas只有8字节整数, i8和浮点数f8 (见本期 )。

这里是我从一个pandasDataFrame的结构数组的方法。

创build数据框

 import pandas as pd import numpy as np import six NaN = float('nan') ID = [1, 2, 3, 4, 5, 6, 7] A = [NaN, NaN, NaN, 0.1, 0.1, 0.1, 0.1] B = [0.2, NaN, 0.2, 0.2, 0.2, NaN, NaN] C = [NaN, 0.5, 0.5, NaN, 0.5, 0.5, NaN] columns = {'A':A, 'B':B, 'C':C} df = pd.DataFrame(columns, index=ID) df.index.name = 'ID' print(df) ABC ID 1 NaN 0.2 NaN 2 NaN NaN 0.5 3 NaN 0.2 0.5 4 0.1 0.2 NaN 5 0.1 0.2 0.5 6 0.1 NaN 0.5 7 0.1 NaN NaN 

定义函数来从pandasDataFrame中创build一个numpy结构数组(不是一个logging数组)。

 def df_to_sarray(df): """ Convert a pandas DataFrame object to a numpy structured array. This is functionally equivalent to but more efficient than np.array(df.to_array()) :param df: the data frame to convert :return: a numpy structured array representation of df """ v = df.values cols = df.columns if six.PY2: # python 2 needs .encode() but 3 does not types = [(cols[i].encode(), df[k].dtype.type) for (i, k) in enumerate(cols)] else: types = [(cols[i], df[k].dtype.type) for (i, k) in enumerate(cols)] dtype = np.dtype(types) z = np.zeros(v.shape[0], dtype) for (i, k) in enumerate(z.dtype.names): z[k] = v[:, i] return z 

使用reset_index创build一个新的数据框架,其中包含索引作为其数据的一部分。 将该dataframe转换为结构数组。

 sa = df_to_sarray(df.reset_index()) sa array([(1L, nan, 0.2, nan), (2L, nan, nan, 0.5), (3L, nan, 0.2, 0.5), (4L, 0.1, 0.2, nan), (5L, 0.1, 0.2, 0.5), (6L, 0.1, nan, 0.5), (7L, 0.1, nan, nan)], dtype=[('ID', '<i8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')]) 

编辑:更新df_to_sarray,以避免错误调用与python 3.encode()感谢约瑟夫·加文和翡翠的评论和解决scheme。

除了meteore的回答,我find了代码

 df.index = df.index.astype('i8') 

不适合我 所以我把我的代码放在这里,以方便其他人坚持这个问题。

 city_cluster_df = pd.read_csv(text_filepath, encoding='utf-8') # the field 'city_en' is a string, when converted to Numpy array, it will be an object city_cluster_arr = city_cluster_df[['city_en','lat','lon','cluster','cluster_filtered']].to_records() descr=city_cluster_arr.dtype.descr # change the field 'city_en' to string type (the index for 'city_en' here is 1 because before the field is the row index of dataframe) descr[1]=(descr[1][0], "S20") newArr=city_cluster_arr.astype(np.dtype(descr)) 

感谢菲尔的回答,这很好。

回复

没有为我工作,错误:TypeError:数据types不明白 – 约瑟夫加文2月13日在17:55

我使用python 3,并得到相同的错误。 然后我删除.encode(),然后expression式如下。

 types = [(cols[i], df[k].dtype.type) for (i, k) in enumerate(cols)] 

那么它的工作。

从dataframe导出到arcgis表时遇到了类似的问题,偶然发现了一个来自usgs的解决scheme( https://my.usgs.gov/confluence/display/cdi/pandas.DataFrame+to+ArcGIS+Table )。 总之你的问题有一个类似的解决scheme:

 df Out[109]: ABC ID 1 NaN 0.2 NaN 2 NaN NaN 0.5 3 NaN 0.2 0.5 4 0.1 0.2 NaN 5 0.1 0.2 0.5 6 0.1 NaN 0.5 7 0.1 NaN NaN np_data = np.array(np.rec.fromrecords(df.values)) np_names = df.dtypes.index.tolist() np_data.dtype.names = tuple([name.encode('UTF8') for name in np_names]) np_data Out[113]: array([( nan, 0.2, nan), ( nan, nan, 0.5), ( nan, 0.2, 0.5), ( 0.1, 0.2, nan), ( 0.1, 0.2, 0.5), ( 0.1, nan, 0.5), ( 0.1, nan, nan)], dtype=(numpy.record, [('A', '<f8'), ('B', '<f8'), ('C', '<f8')]))