分割数据框中的每一行,并为每个元素添加值,避免出现NaN

时间:2018-08-22 20:42:29

标签: python pandas

问题源自这里:Split every row in df and add value to each element

这是更新的df:

df = pd.DataFrame({'user_index': [3590,63, 15], 'movie_index': [1514,563, 9], 
'genre_index':['10|12|17|35', '4|2|1|8', None], 'cast_index':['46|534', None, '9|27']})

要获得想要的数据框,在其中向每个元素添加一个值,我尝试:

offset_dct = {'user_index': 2, 'genre_index': 5}
df.astype(str).fillna('').apply(lambda x: [
[int(z) + offset_dct.get(x.name, 0) for z in y.split('|') if z is not None else []] for y in x])

但它返回了一个错误:

ValueError: ("invalid literal for int() with base 10: 'nan'", 'occurred at index genre_index')

如果没有“ NaN”,则此代码将完美运行:

offset_dct = {'user_index': 2, 'genre_index': 5}
df = df.fillna('').astype(str).apply(lambda x: [
    [int(z) + offset_dct.get(x.name, 0) for z in y.split('|')] for y in x])

问题在于构建我想忽略NaN的列表理解。

任何解决的帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

问题似乎出在astypefillna调用的顺序中。

>>> df.astype(str).fillna('')
user_index movie_index  genre_index cast_index
0       3590        1514  10|12|17|35     46|534
1         63         563      4|2|1|8       None
2         15           9         None       9|27

如果您切换两种方法的顺序,则会得到一些有用的信息:

>>> df.fillna('').astype(str).apply(lambda x: [ [int(z) + offset_dct.get(x.name, 0) for z in y.split('|') if z] for y in x])
  user_index movie_index       genre_index cast_index
0     [3592]      [1514]  [15, 17, 22, 40]  [46, 534]
1       [65]       [563]     [9, 7, 6, 13]         []
2       [17]         [9]                []    [9, 27]

您的原始列表理解中也有错误。您不能在列表理解的if条件中放置else子句。 if条件纯粹是用来告诉理解要保留哪些值的。如果您想根据每个项目的值来做不同的事情,则需要将该逻辑放入理解的函数部分(可能使用lambda表达式)。但是对于这个特定的问题,除了我上面写的以外,您不需要其他任何东西。

答案 1 :(得分:0)

两步法怎么样?

  1. 转换为列表:

    df = df.applymap(lambda x: x if pd.isna(x) else str(x).split('|'))
    
  2. 添加:

    offset_dct = {'user_index': 2, 'genre_index': 5}
    for k,v in offset_dct.items():
        df[k] = df[k].map(lambda x: [int(i)+5 for i in x] if isinstance(x,list) else x)