2017-06-21 188 views
0

我的問題來自於Phil的this answer。 代碼如何獲得<class'numpy.str'>而不是<class'numpy.object _'>

df = pd.DataFrame([[1,31,2.5,1260759144], [1,1029,3,1260759179], 
        [1,1061,3,1260759182],[1,1129,2,1260759185], 
        [1,1172,4,1260759205],[2,31,3,1260759134], 
        [2,1111,4.5,1260759256]], 
        index=list(['a','c','h','g','e','b','f',]), 
        columns=list(['userId','movieId','rating','timestamp'])) 
df.index.names=['ID No.'] 
df.columns.names=['Information'] 

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 
# df[k].dtype.type is <class 'numpy.object_'>,I want to convert it to numpy.str 
    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 
sa = df_to_sarray(df.reset_index()) 
print(sa) 

菲爾的回答運作良好,而如果我運行

sa = df_to_sarray(df.reset_index()) 

我會得到下面的結果。

array([('a', 1, 31, 2.5, 1260759144), ('c', 1, 1029, 3.0, 1260759179), 
     ('h', 1, 1061, 3.0, 1260759182), ('g', 1, 1129, 2.0, 1260759185), 
     ('e', 1, 1172, 4.0, 1260759205), ('b', 2, 31, 3.0, 1260759134), 
     ('f', 2, 1111, 4.5, 1260759256)], 
     dtype=[('ID No.', 'O'), ('userId', '<i8'), ('movieId', '<i8'), ('rating', '<f8'), ('timestamp', '<i8')]) 

我希望我能得到dtype如下。

dtype=[('ID No.', 'S'), ('userId', '<i8'), ('movieId', '<i8'), ('rating', '<f8'), ('timestamp', '<i8')] 

字符串而不是對象。

我測試了df [k] .dtype.type的類型,我發現它是<class 'numpy.object_'>,我想將它轉換爲numpy.str。怎麼做?

+0

你試過'''df [col] .astype(str)'''? –

+0

'types'是iist。所以你應該能夠改變第一個元組。這可能是'('ID號','O')'。 – hpaulj

+0

我只會將'object'類型轉換爲'string',對於類型爲'int'的其他列,我想將它們保留爲'int'。 – Renke

回答

1

reset_index之後數據幀的dtype是對象和數字的混合。索引已被渲染爲對象,而不是字符串。

In [9]: df1=df.reset_index() 
In [10]: df1.dtypes 
Out[10]: 
Information 
ID No.  object 
userId   int64 
movieId  int64 
rating  float64 
timestamp  int64 
dtype: object 

df1.values是(7,5)對象dtype數組。

有了正確dtype,你的方法確實很好(我是PY3使用「U2」):

In [31]: v = df1.values 
In [32]: dt1=np.dtype([('ID No.', 'U2'), ('userId', '<i8'), ('movieId', '<i8'), 
    ...: ('rating', '<f8'), ('timestamp', '<i8')]) 
In [33]: z = np.zeros(v.shape[0], dtype=dt1) 
In [34]: 
In [34]: for i,k in enumerate(dt1.names): 
    ...:  z[k] = v[:, i] 
    ...:  
In [35]: z 
Out[35]: 
array([('a', 1, 31, 2.5, 1260759144), ('c', 1, 1029, 3. , 1260759179), 
     ('h', 1, 1061, 3. , 1260759182), ('g', 1, 1129, 2. , 1260759185), 
     ('e', 1, 1172, 4. , 1260759205), ('b', 2, 31, 3. , 1260759134), 
     ('f', 2, 1111, 4.5, 1260759256)], 
     dtype=[('ID No.', '<U2'), ('userId', '<i8'), ('movieId', '<i8'), ('rating', '<f8'), ('timestamp', '<i8')]) 

因此,技巧是從數據幀推導dt1

編輯types施工後是一個選項:

In [36]: cols=df1.columns 
In [37]: types = [(cols[i], df1[k].dtype.type) for (i, k) in enumerate(cols)] 
In [38]: types 
Out[38]: 
[('ID No.', numpy.object_), 
('userId', numpy.int64), 
('movieId', numpy.int64), 
('rating', numpy.float64), 
('timestamp', numpy.int64)] 
In [39]: types[0]=(types[0][0], 'U2') 
In [40]: types 
Out[40]: 
[('ID No.', 'U2'), 
('userId', numpy.int64), 
('movieId', numpy.int64), 
('rating', numpy.float64), 
('timestamp', numpy.int64)] 
In [41]: 
In [41]: z = np.zeros(v.shape[0], dtype=types) 

施工期間調整列D型也可以工作:

def foo(atype): 
    if atype==np.object_: 
     return 'U2' 
    return atype 
In [59]: types = [(cols[i], foo(df1[k].dtype.type)) for (i, k) in enumerate(cols)] 

在這兩種情況下,我們不得不提前,我們要打開知道將object列轉換爲特定的string類型,而不是更通用。

我不知道足夠的pandas說我們提取數組之前是否可以更改該列的dtype。由於列dtype的混合,.values將是一個對象dtype。

+0

謝謝,你的建議有效。 – Renke

相關問題