将数据帧列分解为多行(类型错误:无法将数据从 dtype('int64') 强制转换为 dtype('int32'))



我将尝试使用此数据创建一个数据帧:

test1   test2                 test3
test    [test1, test2]        [testbelongsto1, testbelongst2]

像这样:

test1   test2                 test3
test    test1                 testbelongsto1
test    test2                 testbelongsto2

我发现这个问题答案 https://stackoverflow.com/a/38652414 看起来正是我需要的,对吗? 有很多问题回答了我的问题。

但是,无论我尝试什么,我都会遇到此错误:

TypeError: Cannot cast array data from dtype('int64') to dtype('int32') according to the rule 'safe'

使用此功能(请参阅链接(:

def explode(self, df, columns):
idx = np.repeat(df.index, df[columns[0]].str.len())
a = df.T.reindex_axis(columns).values
concat = np.concatenate([np.concatenate(a[i]) for i in range(a.shape[0])])
p = pd.DataFrame(concat.reshape(a.shape[0], -1).T, idx, columns)
return pd.concat([df.drop(columns, axis=1), p], axis=1).reset_index(drop=True)

重要提示!日期来自read_csv函数。 我需要分解的列是字符串,所以我写了这段代码将它们转换为列表:

df['users'] = df['users'].apply(literal_eval)

尝试了从 dtype 转换为将它们保存为其他格式的所有内容。 但是没有什么能解决问题...

请帮忙

更新: 下面显示了几行的"真实"数据集示例: "test2" => "users" 和 'test3' => 'interest',数组大小相同。

{'index': [0, 1, 2, 3, 4], 'Unnamed: 0': [0, 1, 4, 5, 6], 'users': ['[1, 1, 28, 28, 68]', '[1, 1, 16]', '[32, 37, 66, 67, 54, 117]', '[31, 37, 66, 67, 100, 113, 117]', '[32, 37, 66, 67, 54, 117]'], 'interests': ['[set(), set(), set(), set(), set()]', '[set(), set(), set()]', '[set(), set(), set(), set(), {1535, 1542, 1527}, set()]', '[set(), set(), set(), set(), set(), set(), set()]', '[set(), set(), set(), set(), {1535, 1542, 1527}, set()]']}

更新 2: 好的,这正是我想要的。 我现在得到的当前数据:

`
index       lift        confidence         interests         users
0                                          {333, 333}        1   
0                                          set()             22
0                                          set()             77
0           0           0.75               set()             88
4                                          set()             33
4           3           0.50               set()             44
`

因此,似乎只添加了每个迭代的最后一个。 这就是我想要的:

`
index       lift        confidence         interests         users
0           88          0.33               344,              1  
0           88          0.33               333               1   
0           88          0.33               set()             22
0           88          0.33               set()             77
0           88          0.33               set()             88
4           38          0.50               set()             33
4           38          0.50               set()             44
`

所以我想要的是每个数据行(系列(每个用户重复,每个用户的兴趣也是如此。

如果您可以信任您的数据不包含恶意字符串,那么您可以使用eval将字符串转换为 Python 对象。不过要非常小心 - 理论上,恶意字符串可以在您的计算机上运行任意代码!

在强调了eval的危险之后,您可以使用apply(pd.Series)技巧解析和重塑数据帧:

import pandas as pd
df = pd.DataFrame({'test': [0, 1, 4, 5, 6], 'test2': [0, 10, 40, 50, 60], 'users': ['[1, 1, 28, 28, 68]', '[1, 1, 16]', '[32, 37, 66, 67, 54, 117]', '[31, 37, 66, 67, 100, 113, 117]', '[32, 37, 66, 67, 54, 117]'], 'interests': ['[set(), set(), set(), set(), set()]', '[set(), set(), set()]', '[set(), set(), set(), set(), {1535, 1542, 1527}, set()]', '[set(), set(), set(), set(), set(), set(), set()]', '[set(), set(), set(), set(), {1535, 1542, 1527}, set()]']})
for col in df.columns.difference(['test', 'test2']):
df[col] = df[col].apply(eval)
interests = df['interests'].apply(pd.Series)
interests = interests.stack().apply(lambda x: pd.Series(list(x)))
users = df['users'].apply(pd.Series)
users = users.stack()
result = pd.concat({'users': users, 'interests':interests}, axis=1)
result = result.stack() 
result['users'] = result['users'].ffill()
result.index = result.index.droplevel(level=[1,2])
result = df.drop(['interests','users'], axis=1).join(result)
print(result)

收益 率

test  test2  interests  users
0     0      0        NaN    1.0
0     0      0        NaN    1.0
0     0      0        NaN   28.0
0     0      0        NaN   28.0
0     0      0        NaN   68.0
1     1     10        NaN    1.0
1     1     10        NaN    1.0
1     1     10        NaN   16.0
2     4     40        NaN   32.0
2     4     40        NaN   37.0
2     4     40        NaN   66.0
2     4     40        NaN   67.0
2     4     40     1535.0   54.0
2     4     40     1542.0   54.0
2     4     40     1527.0   54.0
2     4     40        NaN  117.0
3     5     50        NaN   31.0
3     5     50        NaN   37.0
3     5     50        NaN   66.0
3     5     50        NaN   67.0
3     5     50        NaN  100.0
3     5     50        NaN  113.0
3     5     50        NaN  117.0
4     6     60        NaN   32.0
4     6     60        NaN   37.0
4     6     60        NaN   66.0
4     6     60        NaN   67.0
4     6     60     1535.0   54.0
4     6     60     1542.0   54.0
4     6     60     1527.0   54.0
4     6     60        NaN  117.0

主要思想是使用apply(pd.Series)将列表"分解"为列:

In [572]: interests = df['interests'].apply(pd.Series); interests
Out[572]: 
0   1   2    3                   4    5    6
0  {}  {}  {}   {}                  {}  NaN  NaN
1  {}  {}  {}  NaN                 NaN  NaN  NaN
2  {}  {}  {}   {}  {1535, 1542, 1527}   {}  NaN
3  {}  {}  {}   {}                  {}   {}   {}
4  {}  {}  {}   {}  {1535, 1542, 1527}   {}  NaN

由于您也希望"分解"集合,请再次应用pd.Series技巧:

In [573]: interests = interests.stack().apply(lambda x: pd.Series(list(x))); interests
Out[573]: 
0       1       2
0 0     NaN     NaN     NaN
1     NaN     NaN     NaN
2     NaN     NaN     NaN
3     NaN     NaN     NaN
4     NaN     NaN     NaN
1 0     NaN     NaN     NaN
1     NaN     NaN     NaN
2     NaN     NaN     NaN
2 0     NaN     NaN     NaN
1     NaN     NaN     NaN
2     NaN     NaN     NaN
3     NaN     NaN     NaN
4  1535.0  1542.0  1527.0
...

users列执行相同操作后,将两个数据帧合并为一个:

result = pd.concat({'users': users, 'interests':interests}, axis=1)

将内列索引级别移动到索引,并在用户有多个兴趣时向前填充users列以users值:

result = result.stack() 
result['users'] = result['users'].ffill()
#        interests  users
# 0 0 0        NaN    1.0
#   1 0        NaN    1.0
#   2 0        NaN   28.0
#   3 0        NaN   28.0
#   4 0        NaN   68.0
# 1 0 0        NaN    1.0
#   1 0        NaN    1.0
#   2 0        NaN   16.0
# 2 0 0        NaN   32.0
#   1 0        NaN   37.0
#   2 0        NaN   66.0
#   3 0        NaN   67.0
#   4 0     1535.0   54.0
#     1     1542.0   54.0
#     2     1527.0   54.0
# ...

最后,删除最里面的 2 个索引级别并将result连接回df

result.index = result.index.droplevel(level=[1,2])
result = df.drop(['interests','users'], axis=1).join(result)

相关内容

最新更新