【问题标题】:Adding new column from existing columns using pd.Series() creates NaN values使用 pd.Series() 从现有列添加新列会创建 NaN 值
【发布时间】:2017-11-06 05:43:21
【问题描述】:

我想根据现有列向 DataFrame 添加一个新列。新列只是三列的三个值的元组:

df0.shape
# (5410185, 17)
new_col = pd.Series(list(zip(df0['a'], df0['b'], df0['c'])))
new_col.shape
# (5410185,)
new_col.isnull().sum()
# 0
df0['abc'] = new_col
df0['abc'].isnull().sum()
# 14334

我在示例 df 上尝试了相同的方法,它按预期工作:

test = pd.DataFrame(np.random.randint(0,1000,100000000).reshape(1000000,100))
test['new'] = pd.Series(list(zip(test[1], test[2], test[3])))
test['new'].isnull().sum()
# 0

'assign' 也产生相同的结果:

df0 = df0.assign(new_col2 = pd.Series(list(zip(df0['a'], df0['b'], df0['c']))))
df0['new_col2'].isnull().sum()
# 14334

我发现了两个类似的问题,thisthis。我怀疑我的问题也与索引有关。似乎有 89 个不相同的值:

np.sum(df0.index == new_col.index)
# 89

分配与df0的索引相同的Series:

df0.index = new_col
df0['abc'] = df0.index
df0['abc'].isnull().sum()
# 0

更新 以下是@jezreal 解决方案的一些基准测试:

%time df0['abc'] = pd.Series(list(zip(df0['a'], df0['b'], df0['c'])), index=df0.index)
Wall time: 2.32 s

% time df0['abc'] = df0[['a','b','c']].apply(tuple, axis=1)
Wall time: 1min 42s

%time df0['abc'] = df0.set_index(['a','b','c']).index.values
Wall time: 8.68 s

% time df0['abc'] = pd.Series([tuple(x) for x in df0[['a','b','c']].values.tolist()], index=df0.index)
Wall time: 9.83 s

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    我认为需要与新Seriesdf0 相同的索引来对齐数据:

    df0['abc'] = pd.Series(list(zip(df0['a'], df0['b'], df0['c'])), index=df0.index)
    

    或者使用apply:

    df0['abc'] = df0[['a','b','c']].apply(tuple, axis=1)
    

    示例:

    df0 = pd.DataFrame({'a':list('abcdef'),
                       'b':[4,5,4,5,5,4],
                       'c':[7,8,9,4,2,3],
                       'D':[1,3,5,7,1,0],
                       'E':[5,3,6,9,2,4],
                       'F':list('aaabbb')}, index=[1,1,2,2,9,10])
    
    print (df0)
        D  E  F  a  b  c
    1   1  5  a  a  4  7
    1   3  3  a  b  5  8
    2   5  6  a  c  4  9
    2   7  9  b  d  5  4
    9   1  2  b  e  5  2
    10  0  4  b  f  4  3
    
    df0['abc'] = pd.Series(list(zip(df0['a'], df0['b'], df0['c'])))
    

    print (df0)
        D  E  F  a  b  c        abc
    1   1  5  a  a  4  7  (b, 5, 8)
    1   3  3  a  b  5  8  (b, 5, 8)
    2   5  6  a  c  4  9  (c, 4, 9)
    2   7  9  b  d  5  4  (c, 4, 9)
    9   1  2  b  e  5  2        NaN
    10  0  4  b  f  4  3        NaN
    
    df0['abc'] = pd.Series(list(zip(df0['a'], df0['b'], df0['c'])), index=df0.index)
    

    df0['abc'] = df0[['a','b','c']].apply(tuple, axis=1)
    
    
    print (df0)
        D  E  F  a  b  c        abc
    1   1  5  a  a  4  7  (a, 4, 7)
    1   3  3  a  b  5  8  (b, 5, 8)
    2   5  6  a  c  4  9  (c, 4, 9)
    2   7  9  b  d  5  4  (d, 5, 4)
    9   1  2  b  e  5  2  (e, 5, 2)
    10  0  4  b  f  4  3  (f, 4, 3)
    

    【讨论】:

    • 谢谢,它有效。 “应用”也有效,但我倾向于尽可能避免它,因为它非常慢。使用其他方法需要 2.32 秒,使用 apply! 需要 1 分 42 秒! (有 % 时间,而不是 % timeit)
    • 是的,那么df0['abc'] = df0.set_index(['a','b','c']).index.values 呢?
    • df0['abc'] = pd.Series([tuple(x) for x in df0[['a','b','c']].values.tolist()], index=df0.index) ?
    • 我没有测试,但是zip应该是最好的,因为纯python。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-12
    • 2021-01-02
    • 1970-01-01
    • 2019-12-27
    • 2015-07-27
    • 2019-07-02
    • 2022-11-25
    相关资源
    最近更新 更多