【问题标题】:How to convert pd.series to np.array, not array of arrays? How to replace nan values?如何将 pd.series 转换为 np.array,而不是数组?如何替换 nan 值?
【发布时间】:2021-07-08 16:22:34
【问题描述】:

我很难将选定的数据从 pd.df 转换为 np.array。相反,我得到了一个数组数组。我现在想知道为什么我不立即返回一个正常的数组,拜托。我知道to_numpy(),但它不会产生预期的结果。我也不能替换 nan 值。请您帮我理解一下,请问这是怎么回事?非常感谢!祝你有美好的一天。

我的小例子:

import pandas as pd
import numpy as np

#prepare the example
d={}
d['key1']=np.array([np.nan,2,np.nan,4])
d['key2']=np.array([5,6,7,8])                 
d['key3']=np.array([9,10,11,12])       
print(d)
print(type(d))

# create example df
df=pd.DataFrame(index=[0,1,2,3,4,5],columns=['A','B'])
df.at[0,'A'] = d
df.at[1,'A'] = d
df.at[2,'A'] = d
df.at[3,'A'] = d
df.at[4,'A'] = d
df.at[5,'A'] = d

df

# extract data from selected rows
res1=df.loc[[1,2,3],'A'].apply(lambda x: x.get('key2')).to_numpy()
print(res1)
print(res1.shape) #(3,)
#res1 is an object filled with arrays.
#Why would I not get back immediately an array (3,4), please?

#How can I get a np.array like this, please?
#res2=np.array([[5, 6, 7, 8],[5, 6, 7, 8],[5, 6, 7, 8]])
#res2.shape #(3,4)

# The solution I found:
res3=np.stack(res1,axis=0)
print(res3)
print(type(res3))
print(res3.shape)
#Is there something better that results immediately in a np.ndarray with (3,4)?

#How can I replace the nan values, please?
res4=df.loc[[1,2,3],'A'].apply(lambda x: x.get('key1')).to_numpy(na_value=0)
print(res4) #nan not 0

谢谢。

编辑:我澄清了第二个问题。例如,我只想用 0 替换 nan。在现实世界的示例中,并非所有 key1 的数组都包含 nan。我需要保持每个数组中的元素数量相同。对不起。有人明白为什么我的例子确实给出了预期的结果吗?谢谢。

【问题讨论】:

    标签: python arrays pandas numpy


    【解决方案1】:

    尝试:

    res4=df.loc[[1,2,3],'A'].str['key1'].values
    #instead of using apply() and lambda use .str['key name'] to get a value of particular key
    res4=np.vstack(res4)
    #it's similar to np.stack() at axis=0
    #Finally:
    res4=np.where(pd.isna(res4),0,res4)
    

    res4的输出:

    array([[0., 2., 0., 4.],
           [0., 2., 0., 4.],
           [0., 2., 0., 4.]])
    

    对您的问题的解释:

    你得到的值是 numpy 的数组系列:

    df.loc[[1,2,3],'A'].str['key1']
    #output:
    1    [nan, 2.0, nan, 4.0]
    2    [nan, 2.0, nan, 4.0]
    3    [nan, 2.0, nan, 4.0]
    Name: A, dtype: object
    

    您可以通过映射类型来检查:

    df.loc[[1,2,3],'A'].str['key1'].map(type)
    #output:
    1    <class 'numpy.ndarray'>
    2    <class 'numpy.ndarray'>
    3    <class 'numpy.ndarray'>
    Name: A, dtype: object
    
    #OR  
    #just by:
    
    df.loc[[1,2,3],'A'].str['key1'].values
    
    #output:
    array([array([nan,  2., nan,  4.]), array([nan,  2., nan,  4.]),
           array([nan,  2., nan,  4.])], dtype=object)
    

    你会得到数组的数组

    注意:to_numpy() 方法中的 na_value 参数不起作用,因为您的 Series 中的值存储在容器中(在您的情况下为 np.array)

    对于list、tuple 和set 也不起作用,因为它们也是容器(或者你可以说是数据结构)

    如果值未存储在容器中,则 na_value=0 将起作用

    考虑以下示例:

    s=pd.Series([5,4,7,np.nan,np.nan])
    #Let's say I have this Series
    df=pd.DataFrame(data=[[5,4,np.nan,np.nan,6],[2,np.nan,5,np.nan,7]]).T
    #And this dataframe
    #So the values inside Series and Dataframe are not stored in a container(the datatype is float)
    

    现在我可以轻松使用to_numpy() 方法的na_value 参数:

    s.to_numpy(na_value=0)
    #output of above code:
    array([5., 4., 7., 0., 0.])
    df.to_numpy(na_value=0)
    #output of above code:
    array([[5., 2.],
           [4., 0.],
           [0., 5.],
           [0., 0.],
           [6., 7.]])
    

    更新:

    如上所述,to_numpy() 方法中的 na_value 参数不起作用,因为您的 Series 中的值存储在容器中(在您的情况下为 np.array)

    您从带​​有键 'key1' 的 dict 中得到一个 值数组(数组是一个保存值的容器)

    考虑以下示例:

    d={}
    d['key1']=np.array([np.nan,2,np.nan,4])
    d['key2']=np.array([5,6,7,8])                 
    d['key3']=np.array([9,10,11,12])       
    d1={}
    d1['key1']=np.nan
    d1['key2']=np.array([5,6,7,8])                 
    d1['key3']=np.array([9,10,11,12]) 
    df=pd.DataFrame(index=[0,1,2,3],columns=['A','B'])
    df.at[0,'A'] = d
    df.at[1,'A'] = d
    df.at[2,'A'] = d1
    df.at[3,'A'] = d1
    

    现在如果你使用na_value 参数你会得到:

    df['A'].str['key1'].to_numpy(na_value=0)
    #output:
    array([array([nan,  2., nan,  4.]), array([nan,  2., nan,  4.]), 0, 0],
          dtype=object)
                                               ^nan are not filled because they are inside the container(np.array)                      
                                                                    ^nan fill with 0
    

    注意:

    如果 Series 包含真正的 dict,那么您可以使用 str['keyname'] 表示法来获取 Series 中该键的值,当然它比 apply() 和匿名函数快

    【讨论】:

    • 感谢您的回复。这似乎也是一种方法。如果您使用过这个to_numpy() 功能,您能帮我更好地理解它吗?请参阅上面我对此的评论。非常感谢您的讨论。
    • @PythonSmurf 更新了答案....请看一下:)
    • 感谢您的详细解释。你的意思是 to_numpy 不能转换 na_values 因为数据来自字典键:值对?抱歉,我在阅读to_numpy() 的文档页面时没有意识到这一点。请问为什么要使用.str 来获取内容?这比apply(lambda x: x.get('key1')).to_numpy(copy=True)好吗?感谢您的耐心和分享您的知识。
    • 感谢您的详细解释。当它说 np.array 时,似乎很难发现这是一个容器。或者这可以通过dtype=object 看到吗?我认为这是一个正常的 np.array。如果出现错误,表明没有被替换,不是更好吗?
    • @PythonSmurf 如果您仔细阅读了答案,那么我已经提到如何检查它是否是容器......而且na_value 也是一个可选参数
    【解决方案2】:

    第一个问题

    打电话给to_numpy() 然后np.stack() 似乎是正确的答案,我想不出更好或更短的方法。

    第二个问题

    我假设您想用零替换 NaN,而不是删除值(并更改形状)。下面的代码做到了:

    res4 = df.loc[[1,2,3],'A'].apply(lambda x: x.get('key1')).to_numpy()
    res4 = np.stack(res4)
    np.where(np.isnan(res4), 0, res4)
    

    np.isnan 生成一个具有相同形状的布尔掩码,np.where 在找到 True 的位置放置 0,否则保留来自 res4 的值。

    【讨论】:

    • 感谢您的回复。我仍然不确定我是否正确理解了to_numpy()。为什么这个函数会返回一个如此奇怪的充满数组的 numpy ndarray?这是它的定义:pandas.pydata.org/docs/reference/api/… 此函数中的选项之一也是na_value=。在从 df 转换为 np.ndarray 时,我是否不能一次性用它替换 NaN?它还列出了一个带有 dtype 选项的表,但我也不明白它是如何工作的。也许这是一种获得更正常的 np.ndarray 而不是 dtype 对象的方法?
    猜你喜欢
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2023-04-07
    相关资源
    最近更新 更多